One of the most popular features in SharePoint 2010 is Managed Metadata. Provisioning the fields isn’t that trivial though. The Managed Metadata field type inherits from the Lookup field type and with it, all of its provisioning issues plus more. The field uses GUIDs to connect to a term set which means you will need to write code to connect it to your Managed Metadata Service Application instance. The value of a managed metadata field is held at two places; the field itself and a hidden note field. I will go into more detail about that in my next post but the most important thing to know is that without the note field, the taxonomy field brakes. Initially you will need to provision the Note field. The field must be hidden and although SharePoint uses a specific naming convention when it creates this field the most important part is the field type and ID.

<Field Type=”Note”
DisplayName=”My Taxonomy field”
StaticName=”MyTaxonomyFieldTaxHTField0″
Name=”MyTaxonomyField0″
ID=”{43960f53-b5a9-4a63-93c1-e6072c0cf6c3}”
ShowInViewForms=”FALSE”
Required=”FALSE”
Hidden=”TRUE”
CanToggleHidden=”TRUE” />

Now that we have our supporting field, we can go ahead with the taxonomy field itself. There are two field types here: TaxonomyFieldType and TaxonomyFieldTypeMulti. TaxonomyFieldType can be used to provision a field that can contain only one term while TaxonomyFieldTypeMulti is used to provision fields that can have more than one value. In addition, you will also need to specify Mult=”TRUE” if the field is multi-valued. Now for the interesting part; you can configure the entire column here in XML, assuming you know what the IDs of your Taxonomy store is. The field type has a customisation element that reflects the termset you are attaching your field to. In addition, we point the taxonomy field to the note field we provisioned earlier. Be careful with this part since if some values don’t match your termset settings, the field will fail.

<Field Type=”TaxonomyFieldTypeMulti”

DisplayName=”My Taxonomy Field”

Required=”TRUE”

EnforceUniqueValues=”FALSE”

Mult=”TRUE”

Sortable=”FALSE”

ID=”{639dfe92-2781-4958-bf47-b1efa3392a27}”

StaticName=”MyTaxonomyField”

Name=”MyTaxonomyField”>

<Default />

<Customization>

<ArrayOfProperty>

<Property>

<Name>SspId</Name>

</Property>

<Property>

<Name>GroupId</Name>

</Property>

<Property>

<Name>TermSetId</Name>

</Property>

<Property>

<Name>AnchorId</Name>

</Property>

<Property>

<Name>UserCreated</Name>

xmlns:q4=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q4:boolean”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>false

</Property>

<Property>

<Name>Open</Name>

xmlns:q5=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q5:boolean”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>false

</Property>

<Property>

<Name>TextField</Name>

xmlns:q6=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q6:string”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”&gt;{43960f53-b5a9-4a63-93c1-e6072c0cf6c3}

</Property>

<Property>

<Name>IsPathRendered</Name>

xmlns:q7=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q7:boolean”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>true

</Property>

<Property>

<Name>IsKeyword</Name>

xmlns:q8=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q8:boolean”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>false

</Property>

<Property>

<Name>TargetTemplate</Name>

</Property>

<Property>

<Name>CreateValuesInEditForm</Name>

xmlns:q9=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q9:boolean”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>false

</Property>

<Property>

<Name>FilterAssemblyStrongName</Name>

xmlns:q10=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q10:string”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c

</Property>

<Property>

<Name>FilterClassName</Name>

xmlns:q11=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q11:string”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>Microsoft.SharePoint.Taxonomy.TaxonomyField

</Property>

<Property>

<Name>FilterMethodName</Name>

xmlns:q12=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q12:string”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>GetFilteringHtml

</Property>

<Property>

<Name>FilterJavascriptProperty</Name>

xmlns:q13=”http://www.w3.org/2001/XMLSchema&#8221;

p4:type=”q13:string”

xmlns:p4=”http://www.w3.org/2001/XMLSchema-instance”>FilteringJavascript

</Property>

</ArrayOfProperty>

</Customization>

</Field>

Let’s see what some of those customisations mean:

  • SspId: ID of the TermStore which contains the target TermSet. Unless you know your target farm’s TermStore ID, you should leave this blank for now as we will look it up via code.
  • TermSetId: The target TermSet ID. Same rule applies here; leave blank for now as this property will be set via code.
  • IsKeyword: Indicates if the field points to the Enterprise Keywords TermSet
  • CreateValuesInEditForm: Indicates if the user is allowed to create values in the edit form of the list item.
  • IsPathRendered: Indicates if the full path to the term is displayed in values.
  • Open: Indicates whether everyone can create a term. This must match your TermSet setting, otherwise it will fail.
  • TextField: The GUID of the note field we provisioned earlier.

We are now ready to connect our field to the Managed Metadata Service Application instance. We will need to target the correct managed metadata service and one way to achieve this is by the service application name. I am not keen on hard-coding such values but for simplicity it should do just fine.

In my farm I have

  1. A Managed Metadata Service Application with the name: “Samples Metadata”
  2. The Taxonomy of the Metadata Service contains a group called: “Samples”
  3. The Group contains a TermSet named “My Terms”

We now need to connect the field to the TermSet. We will use the server-side object model to access the TermStore and TermSet, assign the required IDs to our site-level field and update the field by pushing changes down to lists and content types that are using it;

var site = properties.Feature.Parent as SPSite;
var session = new TaxonomySession(site);
var field = site.RootWeb.Fields["{639dfe92-2781-4958-bf47-b1efa3392a27}"] as TaxonomyField;
TermStore termStore = session.TermStores["Samples Data"];
Group group = termStore.Groups.GetByName("Samples");
TermSet termSet = group.TermSets["My Terms"];
field.SspId = termSet.TermStore.Id;
field.TermSetId = termSet.Id;
field.TargetTemplate = string.Empty;
field.AnchorId = Guid.Empty;
field.Update(true);

Keep in mind that you will need to add the note field in every content type and list you want to include the taxonomy field.

Advertisements