Karine Bosch’s Blog

On SharePoint

Programmatically provisioning a term set for navigation


I’ve been experimenting with Managed Metadata and one of the things that I’ve been doing is automating the provisioning a navigation term set using the SharePoint server object model.

In your code you will have to add a reference to the Microsoft.SharePoint.Taxonomy.dll.

First you have to find the correct instance of the term store:

   TaxonomySession session = new TaxonomySession(site, true);

   TermStore termStore = session.TermStores[mmsName];

Then you have to find the correct group to which you want to add your term set. In SharePoint 2010 you could only create groups from within the Central Administration and the term sets in these groups could be accessed by any site collection with the correct permissions.

   termGroup = termStore.Groups[groupName];

But in SharePoint 2013 you can also have a group on site collection level. To retrieve this group you have to use a new method:

   termGroup = termStore.GetSiteCollectionGroup(site);

If you want the term set to be used for navigation, you have to add your term set to the local group:

   TermSet termSet = termGroup.CreateTermSet(termsetName);

And you also have to configure that this term set is going to be used for navigation:

   NavigationTermSet navigationTermSet = NavigationTermSet.GetAsResolvedByWeb(termset, site.RootWeb,

                    StandardNavigationProviderNames.CurrentNavigationTaxonomyProvider);

   navigationTermSet.IsNavigationTermSet = true;

Good to know that the NavigationTermSet class is defined in the Microsoft.SharePoint.Publishing.Navigation namespace of the Microsoft.SharePoint.Publishing.dll.

And then you can start creating the hierarchy of terms that is needed for your site navigation:

   Term term = termSet.CreateTerm(termName, 1033);

In the meantime you can also set the friendly URL.

   NavigationTerm navigationTerm = navigationTermset.Terms.Where(

nt => nt.Id == term.Id).FirstOrDefault();

   navigationTerm.FriendlyUrlSegment.Value = termUrl;

You could also set other properties like the Navigation Hover Text, the Simple Link Url or the Target Url. You could also define whether the term should be excluded for global navigation.

But I had a hard time finding how to change the Navigation Node Title programmatically. It seems that there is no property foreseen for this. I tried to set the Title property of the NavigationTerm but this is a read-only property and reflects the name of the term itself.

When working in the user interface, you can also see that you change the Navigation Node Title, which is set to the name of the term by default:

In Reflector I found that NavigationTerm derives from NavigationTermSetItem and that it has a method named SetCustomizableStringCustomValue(Enum, string) which is not publically accessible. The protected enum is defined as follows:

There you can see that there is indeed a property Title that could map the Navigation Node Title.

I found 2 methods on the Term class that I thought I could use: SetCustomProperty(string, string) and SetLocalCustomProperty(string, string). But both methods created a custom property (which is then visible on the Custom Properties tab).

My friend Tom Van Gaever, who works as a PFE at Microsoft Belgium, pointed out to me that you can set custom properties using the SetLocalCustomProperties method and that properties like the Navigation Node Title have a special name:

  • _Sys_Nav_Title: the Navigation Node Title
  • _Sys_Nav_FriendlyUrlSegment: the Friendly Url, also represented by the FriendlyUrlSegment property of the NavigationTerm class.
  • _Sys_Nav_TargetUrl: the target URL, also represented by the TargetUrl property of the NavigationTerm class.
  • _Sys_Nav_TargetUrlForChildTerms: the target URL for child terms, also represented by the TargetUrlForChildTerms property of the NavigationTerm class.
  • _Sys_Nav_CatalogTargetUrl: the catalog target URL, also represented by the CatalogTargetUrl property of the NavigationTerm class.
  • _Sys_Nav_CatalogTargetUrlForChildTerms: the catalog target URL for child terms, also represented by the CatalogTargetUrlForChildTerms property of the NavigationTerm class.

And that was the key to my solution. By executing the SetLocalCustomProperty method on the _Sys_Nav_Title property, I was able to set the Navigation Node Title:

   term.SetLocalCustomProperty("_Sys_Nav_Title", "core business");

If you use that same method with a property name that does not exist, it will create a custom property (which is then visible on the Custom Properties tab); just like the SetCustomProperty method does.

Save your changes to the term store when you’re finished:

   termStore.CommitAll();

December 13, 2013 - Posted by | SharePoint 2013

9 Comments »

  1. Karine,
    Nice post!
    I got chance to work on Term Set in last month. I struggled a lot to find information on this and finally completed the task. The main challenge I faced was, the functionality I have provided is under SharePoint WebPart which is running on SP 2010 foundation as well as standard/enterprise and the foundation do not have the MetaData service so there I have to render WebPart without this new feature. Finally I solved that issue using reflection, I load the Microsoft.SharePoint.Publishing.dll through reflection rather than adding it in project references.

    Thanks,
    Vishal

    Comment by Vishal Gurav | December 17, 2013 | Reply

    • Hi Vishal,
      Thanks for the nice comment! It has been a long time since I posted something useful eh🙂

      Comment by Karine Bosch | December 17, 2013 | Reply

      • I am following your blog for long now its just that I am understanding SharePoint now after spending 5 years with it.😛
        Keep writing, some new things from SharePoint 2013 will be good to try.

        Thanks,
        Vishal

        Comment by Vishal Gurav | December 17, 2013

  2. Karine: As always, very interesting. I’ve been toothcombing the same API looking for a way to programmatically *read* the custom properties, but so far, I’ve come up empty-handed.

    Do you know of any way to access these properties?

    TIA
    Josh

    Comment by Josh Korn | March 19, 2014 | Reply

    • Yes there is, I did is some time ago but I can’t find my piece of code anymore. Temporarily I can’t find anything else then this: http://sharepoint.stackexchange.com/questions/7870/sharepoint-2010-taxonomy-how-to-search-for-a-term-by-custom-property but I’ll try to answer this question this weekend.
      Karine

      Comment by Karine Bosch | March 20, 2014 | Reply

      • Thanks very much for pointing me to the stackexchange page. It did indeed contain the magic nugget.

        It turns out that if I walk through the terms in a term set without trying to resolve them as navigation terms, the Microsoft.SharePoint.Taxonomy.Term object contains a CustomProperties dictionary, which yields exactly what I want. My mistake was hunting for this in the NavigationTerm object.

        The context is somewhat convoluted, but the easy access to custom properties allows me to build a public-facing site where it’s relatively easy to either show or hide branches of the site (quite important if something goes wrong, or you want to retire part of the site).

        Comment by Josh Korn | March 20, 2014

      • Yes indeed, those custom properties can only be retrieved on the Term itself, not on the NavigationTerm. I’m glad the post helped.
        Good luck with your public-facing site. You’ve exciting times ahead🙂

        Comment by Karine Bosch | March 20, 2014

  3. Thanks Karine for the valuable article on taxonomy.
    I have a doubt. I am trying to set the “use this termset for navigation” ( a check box ) on the term store mgmnt tool in central admin –>MMS–> termset1
    May I know what’s the power shell equivalent of this? I did it through UI ,but would be great if I get this on powershell .

    Thnx
    Prasadwt

    Comment by prasadwt | January 19, 2015 | Reply

    • Hi Prasadwt,
      In CSOM, you can set the following:

      navigationTermSet.IsNavigationTermSet = true;

      You can do the same in PowerShell.

      Kind regards,
      Karine Bosch

      Comment by Karine Bosch | May 11, 2015 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: