Programmatically set navigation settings in SharePoint 2013

When working on a project where I needed to set the navigation for newly created sites programmatically, I had a hard time finding the correct properties and methods in the SharePoint object model to change all the navigation settings. After some researching I found that you need no less than 3 different objects representing the navigation of a website to be able to modify all the settings. These examples apply to SharePoint sites with publishing features enabled (navigation options differ on non-publishing sites), and just using the PublishingWeb.Navigation and WebNavigationSettings objects were sufficient for me. Other properties can be found in the SPWeb.Navigation object however.

These are the objects containing navigation properties:

  • web.Navigation (Namespace: Microsoft.SharePoint)
  • publishingWeb.Navigation (Namespace: Microsoft.SharePoint.Publishing)
  • WebNavigationSettings (Namespace: Microsoft.SharePoint.Publishing.Navigation)

Here are examples of how you instantiate these objects:

// Web Navigation
using (var site = new SPSite("http://somesite"))
using (var web= site.OpenWeb())
{
 var navigation = web.Navigation;
}

// PublishingWeb Navigation
var pubWeb = PublishingWeb.GetPublishingWeb(web);

// WebNavigationSettings
var webNavigationSettings = new WebNavigationSettings(web);

Once instantiated, you will be able to modify the navigation using these objects. I will show some examples of how to set different options on the Navigation settings page on a publishing site through code.

Select type of navigation

GlobalAndCurrent

There are two navigations. The Global navigation (also called Top navigation) and the Current navigation (also called left navigation or quicklaunch). Both of these can be set to different to use different sources. They can inherit from their parent (if a subsite only), use managed navigation, or structural navigation. All you need to do is select the webNavigationSettings object, choose which navigation to set, and select a source for that navigation.

webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.TaxonomyProvider;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.PortalProvider;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.Unknown;
webNavigationSettings.CurrentNavigation.Source = StandardNavigationSource.Unknown;

TaxonomyProvider is Managed Metadata Navigation, PortalProvider is structural navigation, InheritFromParentWeb is self-explanatory, and Unknown leaves no radiobutton selected.

Show subsites and pages

To change these options you need to use the PublishingWeb object.

ShowSubsitesAndPages2

pubWeb.Navigation.CurrentIncludeSubSites = false;
pubWeb.Navigation.CurrentIncludePages = false;
pubWeb.Navigation.CurrentDynamicChildLimit = 20;

Managed navigation: Page settings

To change the values of these two checkboxes, use the WebNavigationSettings object again.

DefaultPageSettings

webNavigationSettings.AddNewPagesToNavigation = false;
webNavigationSettings.CreateFriendlyUrlsForNewPages = false;

Managed navigation: Term set

To connect to a term set in code you can do something like this.

MetadataNavigation

// Below code has to be used from within a method of course.
var session = new TaxonomySession(web.Site);
if (session.TermStores.Count != 0)
{
    var termStore = session.TermStores["MyTermStoreName"]; // Standard name is "Managed Metadata Service"
    var group = this.GetTermGroupByName(termStore.Groups, "MyTermGroupName");
    var termSet = this.GetTermSetByName(group.TermSets, "MyTermSetName");
    webNavigationSettings.GlobalNavigation.TermStoreId = termStore.Id;
    webNavigationSettings.GlobalNavigation.TermSetId = termSet.Id;
}

// Support methods
private Group GetTermGroupByName(GroupCollection groupCollection, string name)
{
    foreach (var group in groupCollection)
    {
        if (group.Name == name)
        {
            return group;
        }
    }
    return null;
}

private TermSet GetTermSetByName(TermSetCollection setCollection, string name)
{
    foreach (var set in setCollection
    {
        if (set.Name == name)
        {
            return set;
        }
    }
    return null;
}

Structural navigation: Sorting

Use the PublishingWeb.Navigation to set the ordering of the Structural navigation.

Sorting

pubWeb.Navigation.OrderingMethod = OrderingMethod.Automatic;
pubWeb.Navigation.AutomaticSortingMethod = AutomaticSortingMethod.Title;

Update
Finally, don’t forget to update your objects when you are done with them.

webNavigationSettings.Update();
pubWeb.Update();
web.Update();

These examples are not a complete overview of what you can do with the navigation in SP2013, but the objects I have shown contain most of the properties needed to set the navigation. You just have to look at the object model in Visual Studio to find other options, and most are pretty self-explanatory.

Advertisements

16 thoughts on “Programmatically set navigation settings in SharePoint 2013”

  1. Hello,

    I was testing your code, but for this line
    var webNavigationSettings = new WebNavigationSettings(web);
    what is the name space for WebNavigationSettings?
    I can’t find that class in MSDN.
    Thanks.

    1. Hi, and thanks for your input.

      Namespace for the WebNavigationSettings class is Microsoft.SharePoint.Publishing.Navigation.

      I will update my post to include which using statements are needed.

      Thank you.

      /Johannes

  2. Good morning, I think that this just might be the fix I need! But I’m frightfully new to SharePoint and coding. Do I run this in SP Management Shell or…..? Forgive me if my questions are ignorant, but I’m desperate to try out this fix!

    1. Hi Catherine.

      No need to apologize. =)

      All of my examples are C# programming examples, and cannot be directly applied to use in SP Management Shell (PowerShell). Instead the code can be run in a SharePoint console application, a custom feature receiver, a webpart etc. I cannot say what approach is best for you since I don’t know the context. You can try and search for example: “create SharePoint console application” or “create custom SharePoint feature receiver”, or something of the like.

      However. The code can be translated to PowerShell syntax/language, and can then be used in SP Management Shell, since SP Management Shell can use the same object model (forgive me for the technical terms). That would require you to look up how you can perform the different tasks in PowerShell one by one. But the same logic can be applied, and the names of properties and methods are the same.

      So basically, a fair amount of googling for PowerShell (SP Management Shell) commands are needed. =)

      /Johannes

    1. I’m not sure I understand what you want to achieve here. Are you saying you want to be able to determine the look of the navigation links in code? Because you can’t. Do you want a link to say “This is the home page”, instead of:
      “This is the
      home page”
      Because that you cannot do in the managed metadata term set. For that you need to apply some custom CSS to increase the width of the navigation. Unless there is some option I don’t know of. =)

      /Johannes

      1. Ahh. Well, sure. It’s a bit off topic, but I’ve done it plenty of times. And no need to apologize. It never hurts to ask. =)

        First of all you need to create a custom CSS file and import somewhere, like in a custom master or application page (depends on where you want the changes to show).

        Once you have imported your custom CSS file you can make changes to the navigation using different selectors. A couple of sample selectors:
        Nav. node container: “div#DeltaTopNavigation ul.ms-core-listMenu-root”
        Nav. nodes: “div#DeltaTopNavigation li.static”
        Selected Nav. node: “div#DeltaTopNavigation li.static.selected”

        After that you can just apply whatever styles you want. I don’t know of any finished designs you can simply copy, so my suggestion is to look around the web or just try stuff out. This is really a job for a developer though.

        And of course never try these things out in a production environment. =)

        /Johannes

  3. Hi,

    I’m trying to set the navigation to automatic sorting by creation date, here is my code :

    PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
    var navset = new WebNavigationSettings(web);

    //cocher navigation structurelle
    navset.CurrentNavigation.Source = StandardNavigationSource.PortalProvider;
    //top navigation
    navset.GlobalNavigation.Source = StandardNavigationSource.PortalProvider;
    pubWeb.Navigation.GlobalIncludePages = false;
    pubWeb.Navigation.GlobalIncludeSubSites = true;

    pubWeb.Navigation.OrderingMethod = OrderingMethod.Automatic;
    pubWeb.Navigation.AutomaticSortingMethod = AutomaticSortingMethod.CreatedDate;
    pubWeb.Navigation.SortAscending = true;

    //end top navigation
    //
    pubWeb.Navigation.ShowSiblings = false;
    pubWeb.Navigation.CurrentIncludeSubSites = false;
    pubWeb.Navigation.CurrentIncludePages = false;
    pubWeb.Navigation.CurrentDynamicChildLimit = 20;
    navset.Update();
    pubWeb.Update();
    web.Update();
    SPNavigationNodeCollection nodes = web.Navigation.QuickLaunch;

    pubWeb.Close();

    IT’S NOT WORKING 😦

    when I debbug, the pubWeb.Navigation.AutomaticSortingMethod is set to OrderingMethod.Automatic, but once the pubWeb.Update(); is executed the pubWeb.Navigation.AutomaticSortingMethod turn back to the default value (Manual)

    Any idea

    Thanks

    1. Hi.
      I can’t test anything myself right now, so I can’t give you any solid answers. You could try separating changes to the navset and the pubWeb objects. Like this:

      var navset = new WebNavigationSettings(web);
      //Make changes to the navset object…
      navset.Update();

      PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
      //Make changes to the pubWeb object…
      pubWeb.Update();
      __________________________________

      Also, you might want to try separating different modifications to the pubWeb object. Like this:

      PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
      pubWeb.Navigation.GlobalIncludePages = false;
      pubWeb.Navigation.GlobalIncludeSubSites = true;
      pubWeb.Update();

      pubWeb.Navigation.OrderingMethod = OrderingMethod.Automatic;
      pubWeb.Navigation.AutomaticSortingMethod = AutomaticSortingMethod.CreatedDate;
      pubWeb.Navigation.SortAscending = true;
      pubWeb.Update();
      __________________________________

      As I said I can’t really try anything right now. My suggestion is to post the question on http://sharepoint.stackexchange.com/. If you do, reply here with the link to the post. That way I might be able to help there instead. =)

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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s