Tuesday, January 7, 2014

Programmatically provisioning Term Sets, Terms, and Managed Metadata columns in SharePoint 2013

In this post I explain how to provision Term Sets, Terms, and Managed Metadata columns in SharePoint 2013 using C#.

Caveats

  • This is for SharePoint 2013 full trust solutions where the Managed Metadata Service is provisioned
  • The Terms and Term Sets  are provisioned in the default site collection term store, but they could just as easily be provisioned in another term store with the appropriate assignment of privileges.
  • For the purposes of this post, I created a site scoped feature and provision all of the terms in a feature receiver. This is not meant to be an explanation of feature receivers so I don't cover a lot of the details of how to setup a feature receiver.


Provisioning SharePoint 2013 Term Sets in Code


In order to provision term sets in code, you first need to get a reference to the term store. In the example below, I use a feature receiver to provision the term set and associated terms. The feature is a site scoped feature and I use the default site collection term store. When activated on a site collection, it will run the code below to provision the terms.

public class MyFeatureReceiver : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {  
        //Get a reference to the current site
        var site = properties.Feature.Parent as SPSite;

        //Get the Default Site Collection Term Store
        var taxonomySession = new TaxonomySession(site);
        var termStore = taxonomySession.DefaultSiteCollectionTermStore;
        var termStoreGroup = termStore.GetSiteCollectionGroup(site);

        //Create Department Term Set with associate Terms
        var termSet = termStoreGroup.CreateTermSet("Department");
        termSet.CreateTerm("Finance", CultureInfo.CurrentCulture.LCID);
        termSet.CreateTerm("Accounting", CultureInfo.CurrentCulture.LCID);
        var humanResources = termSet.CreateTerm("Human Resources", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Recruiting", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Benefits", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Compensation", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Payroll", CultureInfo.CurrentCulture.LCID);
        termSet.CreateTerm("Operations", CultureInfo.CurrentCulture.LCID);

        termStore.CommitAll();
    }
}

Note that I assign the Human Resources term to a variable ("humanResources") because I need to create child terms. Once I create "humanResources", I can create child terms by using the CreateTerm method on the newly created "humanResources" variable.

This is what the site collection term store looks like once the solution has been deployed and the feature has been activated:


 

Provisioning a Managed Metadata Site Column

In order to provision a managed metadata site column that uses the Human Resources term as an anchor, I just add a little code below "termStore.CommitAll();". Here is the full feature receiver code with the added managed metadata site column linked to the new Human Resources term.

public class MyFeatureReceiver : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {  
        //Get a reference to the current site
        var site = properties.Feature.Parent as SPSite;

        //Get the Default Site Collection Term Store
        var taxonomySession = new TaxonomySession(site);
        var termStore = taxonomySession.DefaultSiteCollectionTermStore;
        var termStoreGroup = termStore.GetSiteCollectionGroup(site);

        //Create Department Term Set with associate Terms
        var termSet = termStoreGroup.CreateTermSet("Department");
        termSet.CreateTerm("Finance", CultureInfo.CurrentCulture.LCID);
        termSet.CreateTerm("Accounting", CultureInfo.CurrentCulture.LCID);
        var humanResources = termSet.CreateTerm("Human Resources", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Recruiting", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Benefits", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Compensation", CultureInfo.CurrentCulture.LCID);
        humanResources.CreateTerm("Payroll", CultureInfo.CurrentCulture.LCID);
        termSet.CreateTerm("Operations", CultureInfo.CurrentCulture.LCID);

        termStore.CommitAll();

        var web = site.RootWeb;
        if (!web.Fields.ContainsFieldWithStaticName("HumanResourcesDepartment"))
        {
             var humanResourcesDepartment = web.Fields.CreateNewField("TaxonomyFieldType", "HumanResourcesDepartment") as TaxonomyField;
             if (humanResourcesDepartment != null)
             {
                 humanResourcesDepartment.StaticName = "HumanResourcesDepartment";
                 humanResourcesDepartment.Title = "Human Resources Department";
                 humanResourcesDepartment.SspId = termStore.Id;
                 humanResourcesDepartment.TermSetId = termSet.Id
                 humanResourcesDepartment.TargetTemplate = string.Empty;
                 humanResourcesDepartment.AnchorId = humanResources.Id;
                 humanResourcesDepartment.Group = "Custom Columns";
                 humanResourcesDepartment.AllowMultipleValues = true;
                 humanResourcesDepartment.Open = false;
             }
             web.Fields.Add(humanResourcesDepartment);
             web.Update();
        }
    }
}

Note that since I have the Human Resources term saved in the humanResources variable, I am able to grab it's id to set the anchor point for my managed metadata column.

Here's what the site column looks like after the feature has been deployed and activated:





Notice how the Term Set Settings are anchored to the Human Resources term in the Department Term Set. Here's how the properties on the new managed metadata field should be set:
  • The SspId should be set to the id of the Term Store to use. In this case I happen to have only one Managed Metadata Service and one Term Store to use. In the code above, I just grab the id from my termStore variable.
  • The TermSetId should be set to the id of the Term Set to use. In this case, my Term Set is "Department". In the code above, I just grab the id from my termSet vaiable..
  • The AnchorId should be set to the id of the term that you would like to anchor on. In a lot of cases, this may be set to null if you want to anchor on the Term Set itself. However, in this case, I want to create a column that allows me to select a department within Human Resources. So, I am going to anchor on the "Human Resources" Term. In the code above, I just grab the id from my humanResources variable.

Enjoy!

3 comments: