From the outside in

The blog of Iain Angus

Declaratively Provision Managed Metadata Column in SharePoint 2010

As part of a project I have been working on we wanted to assign categories to items in SharePoint 2010 and decided to use Managed Metadata. Wictor Wilén has a good post explaining what Managed Metadata is and how to set it up. Like Wictor, I also prefer to provision site columns and content types using a combination of declarative CAML and feature receivers. I followed the Wictors post but found he didn’t add the extra steps required to make the solution work.

I’ve outlined the steps we took to provision a managed metadata column to a site content type.

Step 1 - Create a TaxonomyField and a Note field

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field ID="{087C759A-7BD2-4B66-9CF5-277A3399636D}"
    Type="TaxonomyFieldType"
    DisplayName="MMSCategories"
    ShowField="Term1033"
    Required="TRUE"
    EnforceUniqueValues="FALSE"
    Group="_Custom"
    StaticName="MMSCategories"
    Name="MMSCategories"
     />
  <Field ID="{437B0ED2-A31B-47F7-8C69-6B9DE2C4A4F6}"
    Type="Note"
    DisplayName="MMSCategories_0"
    StaticName="MMSCategoriesTaxHTField0"
    Name="MMSCategoriesTaxHTField0"
    ShowInViewForms="FALSE"
    Required="FALSE"
    Hidden="TRUE"
    CanToggleHidden="TRUE"
    />
</Elements>
Step 2 - Add the TaxonomyField and Note Field to a content type
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100aa33de693811427c886a5d27f17ed23d"
               Name="Taxonomy Spike - MMSContentType"
               Group="Custom Content Types"
               Description="My Content Type"
               Inherits="TRUE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{437B0ED2-A31B-47F7-8C69-6B9DE2C4A4F6}" Name="MMSCategoriesTaxHTField0"/>
      <FieldRef ID="{087C759A-7BD2-4B66-9CF5-277A3399636D}" Name="MMSCategories"/>
    </FieldRefs>
  </ContentType>
</Elements>

Step 3 - Wire up the Note field to the TaxonomyField using a feature receiver

The TaxonomyField has a member called TextField, with the following remark on the MSDN page…

“Every TaxonomyField object contains a related hidden text field that contains a string representation of the taxonomy field value. The hidden text field is identified by the GUID returned by this property.”

…so as well as the defining the Taxonomy Field we also need to define something to store the string representation.

   1:  public override void FeatureActivated(SPFeatureReceiverProperties properties)
   2:  {
   3:      SPSite site = properties.Feature.Parent as SPSite;
   4:      Guid fieldId = new Guid("{087C759A-7BD2-4B66-9CF5-277A3399636D}");
   5:      if (site.RootWeb.Fields.Contains(fieldId))
   6:      {
   7:          TaxonomySession session = new TaxonomySession(site);
   8:   
   9:          if (session.TermStores.Count != 0)
  10:          {
  11:              var termStore = session.TermStores["Managed Metadata Service"];
  12:              var group = termStore.Groups["Test Store"];
  13:              var termSet = group.TermSets["Categories"];
  14:              TaxonomyField field = site.RootWeb.Fields[fieldId] as TaxonomyField;
  15:              // Connect to MMS 
  16:              field.SspId = termSet.TermStore.Id;
  17:              field.TermSetId = termSet.Id;
  18:              field.TargetTemplate = string.Empty;
  19:              field.AnchorId = Guid.Empty;
  20:              field.TextField = new Guid("{437B0ED2-A31B-47F7-8C69-6B9DE2C4A4F6}");
  21:              field.Update(true);
  22:          }
  23:      }
  24:  }

Line 20 is the important one, this is the code that wires the Note field created declaratively to the TaxonomyField.