How to Work with Managed Metadata Columns by Using the SharePoint Client Object Model (Kaushalendra Kumar)

Managed metadata is a hierarchical collection of centrally managed terms that you can define and then use as attributes for items in Microsoft SharePoint Server 2010. Managed terms can act as sources of data for columns in libraries or lists. To manage the taxonomy column by using the server object model, there are APIs available under the Microsoft.SharePoint.Taxonomy namespace. However, handling managed metadata columns by using the client object model requires a different strategy.

Managed Metadata Columns

To work with managed metadata columns by using the SharePoint client object model, it helps to have an understanding of how managed metadata columns store values in lists. Consider the following details:

Managed Metadata Columns are Derived from SPFieldLookup

TaxonomyFieldValue has a WSS identifier that is the LookupId property of the term in the TaxonomyHiddenList list. The TaxonomyHiddenList list can be viewed by navigating to /Lists/TaxonomyHiddenList/AllItems.aspx. This list contains the details of all of the terms that are used in any managed metadata column.

For Each Managed Metadata Column, the List has Two Columns

For every metadata column, there are two columns in the list. One column is created with a field name of type Taxonomy Field and other column is created with the name in format fieldnameTaxHTField0 of type Note. Details of the taxonomy hidden column (fieldnameTaxHTField0) can be found in the XML of the taxonomy field. The XML of a taxonomy field is similar to the following. The TextField highlighted in yellow contains the GUID of the hidden column.

<Field Type="TaxonomyFieldType" DisplayName="Language" List="{df9afe98-76ae-45ff-9367-e8c94fgb72c2}" WebId="e6b4333c-617b-4875-bd5d-10e745d5caa3" ShowField="Term1033" Required="FALSE" EnforceUniqueValues="FALSE" ID="{10c90ea3-94e8-453f-b046-ccf3d7b82c3b}" SourceID="{8b16fadf-a200-429d-9f77-b218863efdba}" StaticName="Language" Name="Language" ColName="int1" RowOrdinal="0" Version="1">
<Default />
<Customization>
<ArrayOfProperty>
- <Property>
<Name>SspId</Name>
<Value xmlns:q1="https://www.w3.org/2001/XMLSchema" p4:type="q1:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">a3c8fc5c-a9ca-46c5-b0c4-fd3f1d1b82f3</Value>
</Property>
- <Property>
<Name>GroupId</Name>
</Property>
- <Property>
<Name>TermSetId</Name>
<Value xmlns:q2="https://www.w3.org/2001/XMLSchema" p4:type="q2:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">23cc4396-6de3-47a7-97a6-111675414126</Value>
</Property>
- <Property>
<Name>AnchorId</Name>
<Value xmlns:q3="https://www.w3.org/2001/XMLSchema" p4:type="q3:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">00000000-0000-0000-0000-000000000000</Value>
</Property>
- <Property>
<Name>UserCreated</Name>
<Value xmlns:q4="https://www.w3.org/2001/XMLSchema" p4:type="q4:boolean" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">false</Value>
</Property>
- <Property>
<Name>Open</Name>
<Value xmlns:q5="https://www.w3.org/2001/XMLSchema" p4:type="q5:boolean" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">false</Value>
</Property>
- <Property>
                    <Name>TextField</Name>
<Value xmlns:q6="https://www.w3.org/2001/XMLSchema" p4:type="q6:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">{6a8b96d5-78a1-4e98-875f-52bcd3ebd95a}</Value>
</Property>
- <Property>
<Name>IsPathRendered</Name>
<Value xmlns:q7="https://www.w3.org/2001/XMLSchema" p4:type="q7:boolean" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">false</Value>
</Property>
- <Property>
<Name>IsKeyword</Name>
<Value xmlns:q8="https://www.w3.org/2001/XMLSchema" p4:type="q8:boolean" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">false</Value>
</Property>
- <Property>
<Name>TargetTemplate</Name>
</Property>
- <Property>
<Name>CreateValuesInEditForm</Name>
<Value xmlns:q9="https://www.w3.org/2001/XMLSchema" p4:type="q9:boolean" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">false</Value>
</Property>
- <Property>
<Name>FilterAssemblyStrongName</Name>
<Value xmlns:q10="https://www.w3.org/2001/XMLSchema" p4:type="q10:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Value>
</Property>
- <Property>
<Name>FilterClassName</Name>
<Value xmlns:q11="https://www.w3.org/2001/XMLSchema" p4:type="q11:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy.TaxonomyField</Value>
</Property>
- <Property>
<Name>FilterMethodName</Name>
<Value xmlns:q12="https://www.w3.org/2001/XMLSchema" p4:type="q12:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">GetFilteringHtml</Value>
</Property>
- <Property>
<Name>FilterJavascriptProperty</Name>
<Value xmlns:q13="https://www.w3.org/2001/XMLSchema" p4:type="q13:string" xmlns:p4="https://www.w3.org/2001/XMLSchema-instance">FilteringJavascript</Value>
</Property>
</ArrayOfProperty>
</Customization>
</Field>

As stated previously, the the TextField is of type Note. The XML for the TextField is similar to the following:

<Field Type="Note" DisplayName="Language_0" StaticName="LanguageTaxHTField0" Name="LanguageTaxHTField0" ID="{6a8b96d5-78a1-4e98-875f-52bcd3ebd95a}" ShowInViewForms="FALSE" Required="FALSE" Hidden="TRUE" CanToggleHidden="TRUE" SourceID="{8b13fadf-a200-429d-9f77-b218843efdba}" ColName="ntext2" RowOrdinal="0" />

Taxonomy Field Data
The data in taxonomy fields is stored in the following format:
Sample Column Name Column Type Sample Value Format of Saved Data
Language Taxonomy Field 2;# English WSS Id ;# Name of Term
LanguageTaxHTField0 Note English | c61d9028-824f-446e-9389-eb9515813a42 Name of Term | GUID of Term

The WSS identifier is a 32-bit integer that uniquely identifies list’s list item containing the taxonomy field. This property behaves similarly to the LookupId property and is used as the lookup identifier on the TaxonomyHiddenList list.

Updating the Manage Metadata Column by Using the Client Object Model

To update the taxonomy column, the two associated columns need to be updated with appropriate values.

To update those columns, perform the following steps:

1. Find the WSS identifier of the term that needs to be set as the value. You can use the following code to get the value of WSS identifier of the term:

Microsoft.SharePoint.Client.List taxonomyList = clientContext.Site.RootWeb.Lists.GetByTitle("TaxonomyHiddenList");

CamlQuery camlQueryForTerm = new CamlQuery();
camlQueryForTerm.ViewXml = @"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='IdForTerm'/>
<Value Type='Text'>" + TermGuidId + @"</Value>
</Eq>
</Where>
</Query>
</View>";

Microsoft.SharePoint.Client.ListItemCollection termItems = taxonomyList.GetItems(camlQueryForTerm);
clientContext.Load(termItems);
clientContext.ExecuteQuery();

TermGuidId is the GUID of the term to be set as the value.

2. If there is an entry in the TaxonomyHiddenList list for the given term then the values can be updated by using the WSS identifier. If the TaxonomyHiddenList list does not contain an entry for the given term then the scenario is different.

If there is no entry for the term then the WSS identifier must be set as -1. The following table describes the sample format in which to save the data:

Column Type Format (term exists in TaxonomyHiddenList list) Format (term does not exist in TaxonomyHiddenList list)
Taxonomy field WSS Id ;# Name of term -1 ;# Name of term | GUID of term
Note field Name of term | GUID of term Name of term | GUID of term

The following is the code to update the value based on the CAML query results from step 1:

if(termItems.Count > 0)
{
Microsoft.SharePoint.Client.ListItem termItem = termItems[0];
splistItem[ColumnName] = termItem["ID"] + ";#English";
splistItem[TextColumnName] = "English |c61d9028-824f-446e-9389-eb9515813a42";
}
else
{
splistItem[ColumnName] = "-1;#English|c61d9028-824f-446e-9389-eb9515813a42";
splistItem[TextColumnName] = "English|c61d9028-824f-446e-9389-eb9515813a42";
}
splistItem.Update();
context.ExecuteQuery();

For metadata columns with multiple values, the values should be separated by ;# . For example, more than one value can be saved in the format given below, based on whether the terms already exist in the TaxonomyHiddenList list.

  • If there is entry in the TaxonomyHiddenList list, use the following:

splistItem[ColumnName] = "2;#English;#3;#French";
splistItem[TextColumnName] = "English|c61d9028-824f-446e-9389-eb9515813a42;#
French|de1d9028-824f-556e-9389-ac9515813a56";

  • If there is no entry in the TaxonomyHiddenList list, use the following:

splistItem[ColumnName] = "-1;#English|c61d9028-824f-446e-9389-eb9515813a42;#
-1;#French|de1d9028-824f-556e-9389-ac9515813a56";
splistItem[TextColumnName]= English|c61d9028-824f-446e-9389-eb9515813a42;# French|de1d9028-824f-556e-9389-ac9515813a56";

In this post, I discussed how managed metadata columns can be handled by using the client object model to update the different columns with appropriate values.

Additional Resources

For more information on the topics covered in this post, see the following resources:

Managing Enterprise Metadata in SharePoint Server 2010 (ECM)
Using the Client Object Model
Metadata and Taxonomy Programming Model in SharePoint Server 2010 (ECM)

Technorati Tags: Kaushalendra Kumar,managed metadata columns,SharePoint client object model