Pages

Wednesday, July 17, 2013

Programmatically assinging nested Terms to “Taxonomy” column – Managed Metadata

According to me, Managed Metadata is one of the greatest additions to SharePoint. There are many advantages of using Managed Metadata Service and needless to mention the flexibility and the ease of maintenance it provides to maintain enterprise data. However, these details are out of scope as far as this blog is concerned.

Creating Taxonomy columns which uses Managed Metadata Service to bind the data through UI is straight forward. However, to do it programmatically would require considering few factors. There are many blogs which speak about this, but the one which stands out highlighting the details (as far as I am considered) is here:
http://www.sharepointconfig.com/2011/03/the-complete-guide-to-provisioning-sharepoint-2010-managed-metadata-fields/

This article speaks about creating a taxonomy column and binding the TermSet for that created column.

So far so good, but now I want to bind the taxonomy columns to terms or nested terms and not the termset. This is something I could not find over web and therefore this blog. Consider the example where:
  • “Group Name” is “Vehicles”;
    • “TermSet” are “Cars”, “Trucks” etc
      • “Terms” are “Honda”, “Toyota” etc
        • “Terms inside Honda” are “Civic”, “Accord”, “CRV” etc
        • “Terms inside Toyota” are “Camry”, “Corolla”, “Prius” etc
Now I want to create a taxonomy column which would allow me to select only “Honda” make “Cars”. Here I have nested terms and I cannot bind the column to termset “Cars” or “Trucks” as I want users to select only “Honda” vehicles for one list and another list which would have only “Toyota” vehicles selectable for a different Taxonomy field.

Solution: Below is the code block which would do the expected (observe code assignment for “AnchorId” which was assigned to Guid.Empty for TermSet in the link shared earlier)

public static void AssignTermToTaxonomyField(SPSite site, Guid fieldId, string termGroup, string termSetName, string termName)
{
if (site == null)
{
throw new ArgumentNullException(“site”);
}
if (site.RootWeb.Fields.Contains(fieldId))
{
TaxonomySession session = new TaxonomySession(site);
if (session.DefaultKeywordsTermStore != null)
{
// get the default metadata service application   
TermStore termStore = session.DefaultKeywordsTermStore;
Group group = (from g in termStore.Groups where g.Name.ToLower() == termGroup.ToLower() select g).FirstOrDefault();
if (group != null && !(string.IsNullOrEmpty(termName)))
{
TermSet termSet = group.TermSets[termSetName];
TaxonomyField field = site.RootWeb.Fields[fieldId] as TaxonomyField;
foreach (Term term in termSet.Terms)
{
if (term.Name.ToLower() == termName.ToLower())
{
  // connect the field to the specified term  
field.SspId = term.TermStore.Id;
field.TermSetId = termSet.Id;
field.TargetTemplate = string.Empty;
field.AnchorId = term.Id;
field.Update();
break;
}
}
}
}
else
{
throw new ArgumentException(string.Format(“DefaultKeywordsTermStore not found in site {0}”, site.Url));
}
}
else
{
throw new ArgumentException(string.Format(“Field {0} not found in site {1}”, fieldId, site.Url), “fieldId”);
}
}

So the points to remember are:
  • Assign Site Column’s “SspId” to Term’s TermStoreId (Ex: Honda or Toyota)
  • Assign Site Column’s “TermSetId” to Term’s TermSetId (nested terms would also be part of the same termsets only)  (Ex: Cars)
  • **Assign Site Column’s “AnchorId” to the actual nested term’s Id which we want to map (Ex: Honda or Toyota)
Hope this helps and Thank you for visiting my blog!