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,
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: