Programmatically creating MMS (Taxonomy) fields

It’s a common task to create SharePoint Fields (Columns) through code, and to deploy it to the SharePoint server as a feature. This process is actually quite an easy one: there is Visual Studio item called “Site Column” which you can add to the SharePoint Solution. It is change the appropriate column type and names, include the new Site Column in a feature, and voila, it is ready to be deployed.

The story is a bit different with the columns of the MMS (Taxonomy) types, though.

First of all, after you create the Taxonomy field, you will need to create a hidden Note field, which will be associated with the Taxonomy field. You need to specify a Guid for the Note field.

Taxonomy field schema:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Field ID="{85A452FD-37E7-47B0-A4F1-910EDC0E0650}"
         Type="TaxonomyFieldType"
         DisplayName="Order Status"
         ShowField="Term1033"
         Required="FALSE"
         EnforceUniqueValues="FALSE"
         Group="DeltaAccess"
         StaticName="OrderStatus"
         Name="OrderStatus"/>
</Elements>

Hidden note field schema:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field
    ID="{f47685b7-93eb-45da-8227-c59925a0d87e}"
    Name="OrderStatus_Note" StaticName="OrderStatus_Note"
    SourceID="http://schemas.microsoft.com/sharepoint/v3/fields"
    Type="Note"
    DisplayName="OrderStatus_Note"
    Group="DeltaAccess" />
</Elements>

Now, after both fields are created declaratively, and deployed to the site, you will need to 1) Connect the Taxonomy field with the Note field and 2) connect the Taxonomy field to the actual taxonomy – that is the part which we couldn’t do on a declarative way.

We will do that in the FeatureActivated event receiver on the feature we use for deploying the both fields:

SPSite site = properties.Feature.Parent as SPSite;
Guid fieldId = new Guid("{85A452FD-37E7-47B0-A4F1-910EDC0E0650}");
if (site.RootWeb.Fields.Contains(fieldId))
{
    TaxonomySession session = new TaxonomySession(site);
    if (session.TermStores.Count != 0)
    {
        var termStore = session.TermStores["ManagedMetadata_Proxy"];
        var group = termStore.Groups["GroupName"];
        var termSet = group.TermSets["TermSetName"];
        TaxonomyField field = site.RootWeb.Fields[fieldId] as TaxonomyField;

        //set the text field to the id of the OrderStatus_Note field : f47685b7-93eb-45da-8227-c59925a0d87e
        field.TextField = new Guid("{f47685b7-93eb-45da-8227-c59925a0d87e}");

        // Connect to MMS
        field.SspId = termSet.TermStore.Id;
        field.TermSetId = termSet.Id;
        field.TargetTemplate = string.Empty;
        field.AnchorId = Guid.Empty;
        field.Update();
    }
}

And that is basically it.

Warning:

If you don’t set the Note field, everything will seem to function at first, but you will start getting the error:

“The SPListItem being updated was not retrieved with all taxonomy fields.”

errormessage