Tuesday, 18 October 2011

Sharepoint 2010 - Cross site collection navigation

Sharepoint 2010 comes with a pretty good navigation out-of-the-box, but there are still some areas where it's not sufficient and that is navigation that crosses site collection boundaries.

If you are designing a large Sharepoint 2010 site architecture you are probably using site collections because they represent security boundary and can also be placed in a separate content database which allows you to physically segment Sharepoint 2010 content across multiple SQL databases.

Fortunately, there is a pretty simple solution to implement cross site collection navigation which makes navigating accross multiple site collections to feel more like having a site structure in a single site collection.

To achieve this we need to create a custom navigation provider in Sharepoint 2010 web application that pulls its data from xml file which represents our site collection structure. This way we can have flat site collection design where all site collections are created in the same URL path level, but also have them hierarchically organised to better represent our organizational structure.

 Here are the steps to implement custom navigation based on xml file.

Copy/paste the following xml in notepad and name it CustomNavigation.sitemap.

<siteMap>
  <siteMapNode title="Home" description="Home" url="/">
    <siteMapNode title="Products" description="Our products" url="/sites/products">
      <siteMapNode title="Hardware" description="Hardware choices" url="/sites/hardware" />
      <siteMapNode title="Software" description="Software choices" url="/sites/software" />
    </siteMapNode>
    <siteMapNode title="Services" description="Services we offer" url="/sites/services">
        <siteMapNode title="Training" description="Training classes" url="/sites/training" />
        <siteMapNode title="Consulting" description="Consulting services" url="/sites/consulting" />
        <siteMapNode title="Support" description="Supports plans" url="/sites/support" />
    </siteMapNode>
  </siteMapNode>
</siteMap>

Now open the Internet Information Services Manager, expand your Sharepoint web application, right-click the _app_bin folder and click Explore.



 Copy the CustomNavigation.sitemap file to this folder.





Now you need to register the new site map navigation provider by modifying the web.config file of your Sharepoint web application.

Open web.config file (it's located one level above from where you pasted CustomNavigation.sitemap) and enter the following line just below the rest of the already registered providers:

    <siteMap defaultProvider="CurrentNavigation" enabled="true">
      <providers>
    ....
    ....

        <add name="CustomXmlContentMapProvider" siteMapFile="_app_bin/CustomNavigation.sitemap" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
      </providers>
    </siteMap>

Now, maybe you've read on some other blog that you should first copy the following line:

        <add name="SPXmlContentMapProvider" siteMapFile="_app_bin/layouts.sitemap" type="Microsoft.SharePoint.Navigation.SPXmlContentMapProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

and then rename it and just modify siteMapFile path. But in my case this did not work very well. Everything was okay on the root portal site, let's say it's http://sps. But on the http://sps/sites/products I would get wrong relative links: http://sps/sites/products/sites/hardware instead of http://sps/sites/hardware. Modifying the xml file with full URL did not work either so when I tried using the System.Web.XmlSiteMapProvider everything worked as it supposed to do. I guess it's because Sharepoint sees http://sps/sites/products as root of the site and not http://sps. The XmlSiteMapProvider does not have this problem.

The next step is to link our custom navigation provider with the top link navigation bar on the Sharepoint site. We need a Sharepoint Designer 2010 to do this.

Browse to the site collection root site where you want to modify navigation and click on Site Actions > Edit in Sharepoint Designer. Keep in mind that you will have to modify all site collections this way to implement consistent navigation.

We will modify the v4.master so that all pages that are based on v4.master will have the same navigation.



Double click on v4.master and click on "Edit file".



Select the "Split" view then right click on the top link navigation bar and click "Zoom to Contents".

Modify the following:

    <SharePoint:AspMenu
      ID="TopNavigationMenuV4"
      Runat="server"
      EnableViewState="false"
      DataSourceID="topSiteMap"
      AccessKey="<%$Resources:wss,navigation_accesskey%>"
      UseSimpleRendering="true"
      UseSeparateCss="false"
      Orientation="Horizontal"
      StaticDisplayLevels="2"
      MaximumDynamicDisplayLevels="1"
      SkipLinkText=""
      CssClass="s4-tn"/>
    <SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
        <Template_Controls>
            <asp:SiteMapDataSource
              ShowStartingNode="False"
              SiteMapProvider="SPNavigationProvider"
              id="topSiteMap"
              runat="server"
              StartingNodeUrl="sid:1002"/>
        </Template_Controls>
    </SharePoint:DelegateControl>

To look like this:

    <SharePoint:AspMenu
      ID="TopNavigationMenuV4"
      Runat="server"
      EnableViewState="false"
      DataSourceID="topSiteMap"
      AccessKey="<%$Resources:wss,navigation_accesskey%>"
      UseSimpleRendering="true"
      UseSeparateCss="false"
      Orientation="Horizontal"
      StaticDisplayLevels="1"
      MaximumDynamicDisplayLevels="1"
      SkipLinkText=""
      CssClass="s4-tn"/>
            <asp:SiteMapDataSource
              ShowStartingNode="False"
              SiteMapProvider="CustomXmlContentMapProvider"
              id="topSiteMap"
              runat="server"
              StartingNodeUrl="/"/>

Save the v4.master and open your site in a web browser.

Here are the results:



You'll notice that I've also modified the StaticDisplayLevels property from 2 to 1. This represents to which level Sharepoint will display links from the xml file visible on the top link navigation bar and when will the links be placed in a drop-down menu when you hover over the link. The default setting of 2 will place all links from the xml file visible on the top link bar like this:



So there you go, cross site collection navigation as simple as it can be.

18 comments:

  1. howdy, i followed this step by step, however the only thing that changed for me was staticdisplaylevels, sharepoint was still getting content from the old provider and not the new .sitemap file. please help.

    ReplyDelete
  2. Same here. Anything else we need to be doing?

    ReplyDelete
    Replies
    1. Hi, did you manage to get this working?

      Delete
  3. Hoo wee!! This worked perfectly for my portal nav menu (above the standard "global nav bar" which is really the site collection menu). After days of research about the appending of the extra path element, I found this article, changed the provider, and BAM! I now have a two tier menu (one static, one dynamic) defined in a custom sitemap file which is injected into a copy of the v4.master page.

    To the other commenters, you may be using a Publishing Portal template for your site collection. The first thing I figured out is that you can forget about higher-than-site collection navigation using that template. It has its own master page and navigation provider. Team Sites worked great, even for the Up folder with Portal Site Connection configured.

    FYI, I have started work on enabling security trimming for the custom sitemapnodes. You have to add the attribute securityTrimmingEnabled="true" in the provider key in the web.config file, then you can add roles="*" to each node to give everyone access (must be done on root sitemapnode or the whole menu will be hidden). I am still researching how to use other roles, where to configure them, etc. to secure the portal menu items.

    Thanks for the great post, Dinko!
    John C. Pratt
    jpratt@crec.org

    ReplyDelete
    Replies
    1. Hi,

      Did you manage to get the security trimming working for various roles? It will be very kind of you to share your findings.

      Many Thanks
      Mandeep

      Delete
  4. Thanks for this, very clear/helpful. +1 internets.

    ReplyDelete
    Replies
    1. Hi Ryan,

      I followed this link via your comment at http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/4ed39c9b-031c-43f4-a5ed-f161f55f79bd/

      I was trying to implement this and could not get this to work. Did you manage to get it working ? If so please can you help ?

      Thanks
      Jeet

      Delete
  5. BTW, for anyone who couldn't get this to work, please note my observations:
    1. The first time I updated v4master, it all looked correct, but it gave an error about CustomXmlContentMapProvider - I just cancelled out of Designer, restored v4master and did it again in one go before saving - it worked fine.
    2. Notice that in the code that you have to edit, there are at least 3 lines you need to DELETE. I didn't notice that for ages.
    3. Once I had it at least reading the new xml file, I then had to spend a few hours converting our old sitemap in to the new format. This is where I learned you have to be spot on. I'm new to XML formatting so here are my obsertations:
    a) Each URL must be unique or not set at all, i.e remove url="" if you don't want a URL at that node.
    b) & must be replaced by &
    c) % are not allowed, and slashes (%2f), must be a real forward slash.
    d) the only way I could get spaces in (for an SSRS report url we have Live), was to use a real space. I will be happier to change the report url to remove the space, and then update the xml.
    e) if debugging, copy your whole sitemap in to notepad, and then transplant it bit by bit in to xml, building it up - don't try to debug multiple issues at once. There is undoubtedly an xml validation tool to help do this though.
    4. SharePoint Designer 64bit crashed A LOT!

    ReplyDelete
  6. Thank you for this post. It has helped me alot.

    ** Question ***
    Is it possible to apply my selected site theme to the menu?

    ReplyDelete
  7. MMM wil need to try this for our organization.
    Still i have some questions:
    - What happens if you make a new site collection ==> do you need to adjust the XML file with all the links?
    - can you apply the same master page troughout all the site collections?

    ReplyDelete
    Replies
    1. Hi there, you seem to be working on this at the same time as I am , would you be interested in sharing some ideas on implementing this. If so please email me at mandeep.chhabra@yahoo.co.in

      Thanks
      Mandeep

      Delete
  8. After 2 weeks of trying to get this to work overriding the control and the PortalSiteMapProvider.GetChildNodes method, your solution worked like a charm.
    The only thing I've had to change is to set ShowStartingNode="true".
    Thanks man!

    ReplyDelete
    Replies
    1. Hi JS,

      Can you please share your solution. My XML file looks like this:













      But after making the changes, I only see Home with 3 links under it for ICT,Training and SchoolInfo.

      Help much appreciated.

      Thanks
      Mandeep

      Delete
  9. I have managed to get it working. Thanks

    ReplyDelete
  10. Hi,
    i need to apply the sitemap for sitecollections i have a top level site and site collections from each site collection i need to navigate to other sitecollection with the sitemap provider i am not able to do with the above steps. when i click on sitecollection menu link it will append to the current site collection in the url. can any help me on this how i need to prepare the xml to support for sitecollections.

    ReplyDelete
  11. Your solution works perfectly. You have saved me countless hours of phallating about.

    Thank you. Never stop posting any technical solutions you come up with.

    ReplyDelete
  12. There is a easy to understand solution to apply cross website selection routing which makes directing accross several website selections to feel more like having a website structure in a single website selection.

    ReplyDelete
  13. Hi,
    Will this solution work publishing feature enabled with document workspace template?

    ReplyDelete