1,554 articles and 11,130 comments as of Saturday, May 22nd, 2010

Monday, May 17, 2010

SharePoint: Implementing a Custom Navigation Scheme across Multiple Site Collections for the “Non-Developer”

Guest Author: Jay Simcox
The SharePoint Mechanic

Recently I was fortunate enough to have submissions to SharePoint Saturday in Atlanta and Huntsville accepted. What follows is basically a written version of those presentations. I had started this some time back and had never gotten around to finishing it and because I bricked recording the session in Atlanta and couldn’t record in Huntsville I figured the least I could do was to set it all out in writing. Interestingly enough Peter Allen posted a great ARTICLE on the same subject with a different solution, think of this article as the “non-developers” counterpoint.

Microsoft has made great improvements in the SharePoint suite of products over the last several years. There is one area however that needs to be improved that they seem to be ignoring for some reason. I know that making dramatic improvements in SharePoint navigation isn’t as sexy as bringing in better permissions management, more robust reporting, new services that leverage Access, Excel and Visio but the fact of the matter is if your navigation sucks or is difficult to use your users will do all they can to get out of using your shiny new SharePoint portal no matter what version it is and what other features it may offer.

If you’re like me and are a true “Non-Developer” you have may have taken the time to do some reading and research regarding “Web Usability”. One of the keys that I have seen in both the books I have read and websites I have viewed is setting up a navigation scheme or structure that is consistent across the breadth and depth of your site. I personally think that this should apply to SharePoint as well and Microsoft has let us all down by not addressing the ability to easily implement a consistent navigation structure across multiple site collections.

Note that I said “easily”! If you have an architecture that has site collections with nothing but sites under the top level you could probably claim that you were able to easily set up a consistent navigation scheme. But what about those architectures that have a site collection at the top level and then have a mixture of sites and site collections that falls underneath that top level? It isn’t so easily done then.

The Problem

You have built out your environment following best practice guidelines to keep your content databases under 100GB by implementing multiple site collections. Unfortunately as part of your architecture you have identified a number of functional areas that really don’t have a requirement to be a site collection but that should fall under a top, or secondary, level site collection that might have multiple sub site collections under it. Consider the following example:

Your architecture consists of 4 top level “containers” (besides the Home site) each of which is a site collection. They are:

  • Offices – This site collection consists of your corporate offices and it is pretty much a given that all the users in this group are going to use SharePoint for is calendars, some tasking and minimal document management. There is no way that any of the sites under the offices site collection will need to be a separate site collection.
  • Divisions – This site collection consists of your organizations divisional offices. In the course of the requirements gathering process you have determined that at least two divisions are going to heavily use SharePoint and that there is the potential for a large amount of content to be generated in the sites for those divisions. On the flip side of that you also determine that at least two divisions will not use SharePoint heavily and can be housed as sub sites of the Divisions site collection.
  • Products – This division is designed to support the business process surrounding your company’s products. Two products will generate a great deal of content for storage in SharePoint while two products are no longer in production and the sites supporting them will be used only for sustainment purposes and thus will not generate a significant amount of content.
  • Support – This site collection is designed to house 3 support locations for your company only one of which, Graphics Support, will generate a significant amount of content and will require its own site collection. 

So how do you build a navigational scheme that works across all site collections, sites and sub sites that is consistent?

That’s the situation I recently ran into and while the initial answer sounded pretty simple, build a custom site navigation solution; this was anything but the case (well for me anyway). There’s a lot of information on the internet about doing this but most of it is either incomplete, assumes you know something you don’t or requires programming/scripting skills (something I do not have).

What follows is documentation of how I solved this problem. I will:

  1. Lay out the framework of the solution I came up with.
  2. Identify to you the drawbacks of this solution.
  3. Identify to you the benefits of this solution.
  4. Provide step-by-step instructions on how to replicate my solution complete with screenshots.

The Solution

When I started looking into solutions for the problem I was facing I came up with three potential choices:

  1. Configure navigation manually – there are at least 2 disadvantages to this choice:
    1.  The sheer amount of administrative overhead involved.
    2. Designed behavior on the part of SharePoint where in those sites where you have the Publishing feature activated SharePoint will display a tab for the site you are working in to the direct left of the home tab in your global navigation tabs. You can hide that using CSS but you really shouldn’t have to worry with it.
  2. Write custom code to leverage an external data source – if you’re a developer or have scripting skills this would be the way to go. A couple of the most obvious data sources to use would be a SQL database or a SharePoint list. Personally I think if you leverage the SharePoint list you’ll find that managing your site navigation might be simpler because you could delegate the ability to add sites to your site administrators.
  3. Create a custom XMLSiteMapProvider – this is the solution I have come up. We will use a custom site navigation provider that reads the portal structure from an XML file stored in the _app_bin folder and renders that structure to a custom master page.

The steps we are going to follow to implement our solution are:

  1. Create an XML sitemap file.
  2. Edit the web.config file of our website to enable the use of our new sitemap.
  3. Make 5 changes to the default.master page of our site collection.
  4. Create a custom feature that will allow us to activate our customized master page on any site collection in our farm.

The Drawbacks

As with any solution or fix there are going to be drawbacks, some of the most obvious drawbacks to the solution I am proposing follow below:

  1. Links in the navigation menus are not security trimmed.
  2. The sitemap file is not dynamic. Anytime you make a structural change to your portal (add a new site or site collection you want included in the navigation scheme) you’ll need to update the sitemap file manually. In environments where there is rigid configuration management controls in place this could be problematic.
  3. Implementation of this solution requires access to your SharePoint web front ends. This may also be an issue in those environments where access is tightly controlled.
  4. The web.config file for the web application you are applying the solution to will have to be modified. If you have multiple front ends or have extended your web application you will have to maintain multiple instances of the file.
  5. Customizations will not apply to pages in the /_layouts/ directory which uses application.master rather than default.master. Modifying application.master is NOT supported by Microsoft.
  6. This solution is not exceptionally scalable. It works well for those environments where you might have 20 – 30 site collections.

The Benefits

As there are drawbacks there are also benefits to any proposed solution:

  1. One consistent navigation scheme across your site collections and sites.
  2. No .dll to be deployed to the GAC.
  3. Minimal coding.
  4. Can be extended to modify the quick launch.
  5. Navigation the way you want it and not the way that SharePoint thinks you should get it.

You’ll have to determine if this solution is viable for your environment and/or skill set.

Step-by-Step Instructions

Create the XML sitemap file.
The sitemap file is simply an XML file that consists of three components; an xmlns reference, a group of sitemap nodes or elements and within each node (element) several attributes.

Let’s take a look at the components of the sitemap file:

  1. siteMap xmlns – a reference to the sitemap schema at Microsoft.com. This file defines the elements that can appear in the sitemap file and the attributes that can be associated with those elements.
  2. siteMapNode – the siteMapNode defines the navigational element, tab, dropdown or flyout, of your SharePoint architecture.
    1. Keep in mind that like HTML all of your XML elements must be “closed” for example where you have a <siteMapNode> you must also have a </siteMapNode) closing element somewhere in the file.
  3. Element attributes:
    1. Title – kind of obvious that this would be necessary. This will be the test of your link in the tab, dropdown or flyout(s) of your navigation.
    2. Description – optional and it would probably be good to include attribute. Briefly describing the site here would be beneficial to any person assuming your duties at some point in time.
    3. URL – required, relative url’s do work here and using them to me would be a best practice. I try and use relative url’s anywhere I can as a matter of practice.

The following screenshot shows a portion of my siteMap code. I have provided a .zip file at the end of this article that contains the siteMap file as well as all other components of the solution.


Save the file as mainMenu.sitemap in the _app_bin/ folder of Inetpub on your SharePoint server. You could also store the file in the _layouts/1033 folder in the 12 hive if you so desired.

Adding a child node to your navigation scheme.

Inevitably somewhere along the line you are going to add another site collection or site to your farm that also needs to be added to your navigation scheme. As I mentioned one of the drawbacks to this solution is that is not dynamic. So it will be necessary to edit the sitemap file you’ve created and add a reference to your new site collection or site.

  1. Start by finding the parent node in your sitemap file.
  2. Remove the trailing forward slash in the siteMapNode element
  3. Add a child element directly under the parent.
  4. Close the child node siteMapNode element with closing forward slash />

For example if I wanted to add a site for Requisitions under my purchasing Department node I would alter my code as follows:

Before


After

Don’t forget, it is absolutely critical that you close the child node siteMapNode with the trailing forward slash as shown in the screen shot.

Now that the sitemap file has been created where to store it? By default SharePoint uses a layouts.sitemap file that is stored in the _app_bin folder of your SharePoint servers virtual directory in Inetpub. That is where we are going to store our custom sitemap file. I have seen where some people will store their custom sitemap file in the _layouts\1033 folder. This will work as well as the _app_bin folder. I have looked to see if I could find the benefits of one over the other but couldn’t find any kind of concrete evidence that would lead me to believe that one option was significantly better than the other. Maybe one of the web folks here could chime in with their .02 on that.

Edit the web.config to reference our custom sitemap

With our sitemap file created and saved to the appropriate location we’ll move on to adding a single line of code to the web.config file of our SharePoint server. This line of code will tell SharePoint the name of our custom sitemap, where to find it, what “type” or class the custom sitemap provider is using, what version, the culture, and the PublicKeyToken.

Locate the web.config file in the virtual directory of your SharePoint server and take the following steps BEFORE you do anything else.

  1. Right click the web.config and copy the file.
  2. Right click and paste your copy of the web.config back into the virtual directory. This will create a file named “Copy of web.config”

Open the web.config with either Notepad, Visual Studio or Notepad++. Never, ever, use Wordpad to edit the web.config. Wordpad has a lamentable tendency to replace certain characters in your web.config with question marks (?) which tens to break things and can be extremely frustrating and time consuming to fix.

  1. Find the siteMap node in the web.config. It should be about line 156 and will identfiy the default siteMap provider of your SharePoint portal.
  2. Directly under the <siteMap defaultProviders line you’ll see a <providers> node. Just before the </providers> closing tag add the following line of code
  3. <add name="CustomXmlContentMapProvider" siteMapFile="_app_bin/mainMenu.sitemap" type="Microsoft.SharePoint.Navigation.SPXmlContentMapProvider, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
  4. Save your changes.
  5. Restart IIS.

The line we are adding tells SharePoint that there is another sitemap provider available, it’s name, and where the sitemap file is located.

Create the custom master page

We need to create a custom master page that will allow us to leverage our custom sitemap provider and to display flyouts off of our drop downs in the global navigation tabs. Note that I did not say “make modifications to the default.master”. Best practice; never edit the default.master, make a copy and make your changes there. This is what we are going to do.

  1. Open your SharePoint site using SharePoint Designer.
  2. Navigate to the default.master page. The path is _catalogs/masterpage/. If, for some reason, one or both of these folders are empty you’ll need to refresh the view. In the toolbar click “View” and then “Refresh”.
  3. Find the default.master and right click > copy
  4. Make sure that you do not have a folder highlighted and then right click > paste into the masterpage directory. You should now see a file named “default_copy(1).master”.
  5. Double click the new file to open it. If you are prompted to check it out click OK to do so.
  6. We are going to make 5 changes to this file.
    1. Switch to code view
    2. Find the SharePoint:AspMenu element in the page. In my page it was about line 113.
    3. Change the “DataSourceID to “mainMenu” which was the name I saved my sitemap file as. Note that you do not include a file extension here.
    4. Next find the MaximumDynamicDisplayLevels element and change it from the default of 1 to 4. This will allow you to display links 4 levels deep. Be aware that taking your navigation too many levels deep can adversely effect your servers performance.
    5. Next find and copy the “SharePoint:DelegateControl” node. Paste the code you’ve copied directly under the </SharePoint:DelegateControl> closing tag.
    6. In the code you just pasted in change the following 3 items.
      1. Change the ControlId to CustomNavigationDataSource
      2. Change the SiteMapProvider to CustomXmlContentMapProvider
      3. Change the id to mainMenu
  7. Save the file to your desktop. I chose to call it MyCustom.master

The following 2 screenshots show the changes along with notes.




Create the feature to implement our custom master page

Lastly we are going to create the custom feature necessary to push the custom master page we just created across our site collections. A feature is simply a small piece of codethat adds additional functionality to SharePoint. The feature consists of at least 2 xml files, feature.xml and elements.xml, our feature will also include a folder called MasterPages.

Take the following steps to create your feature;

  1. Navigate to the features folder in the 12 hive of your SharePoint server \12\template\features\
  2. Create a new folder in the features folder. Call it CustomMasterPage
  3. Within your new CustomMasterPage folder create another folder named MasterPages and add the MyCustom.master master page you just created to it.
  4. Using your text editor of choice create the feature.xml file and add the following:
    1. Feature Id – this is a GUID or Global Unique Identifier. This can be done using Visual Studio or if you don’t have VS you can use GUIDGen.com. Each feature MUST have a UNIQUE identifier.
    2. Title – “Custom Master Pages” this is the title of your feature and is what you’ll see in the site collection features list.
    3. Description – do yourself a favor and add a description so you know exactly what this feature is being used for.
    4. Version – the SharePoint version in this case 12.0.0.0
    5. Scope – this is the scope that the feature will be deployed at. It could be Farm (the entire farm), Site (this is the Site Collection level) or Web (the site level). We’ll do “Site”
    6. Hidden – is the feature hidden or viewable by site collection and farm administrators. You could hide it and activate using stsadm if you wanted to. We are going to leave it viewable.
    7. DefaultResourceFile – my understanding that this attribute references the core.css file
    8. Xmlns – what xml schema is being used.
    9. ElementsManifest – the location of the Elemnts.xml file we will create in the next step.
  5. Using your text editor of choice create the feature.xml file and add the following:
    1. ModuleName – the ModuleName element allows you to add one or more files to a SharePoint website
    2. URL – where the fileis going to be added, in this case _catalogs/masterpage
    3. Path – the location where the file is located within the file system
    4. RootWebOnly – should the file or page only be available in the root SharePoint site. In this case no.
    5. File Url – your filename in this case MyCustom.master
    6. Type – GhostableInLibrary this specifies that SharePoint store the file in a Document Library.
  6. Now that the files have been created you will need to use stsadm to install your new feature. From the command prompt run the following command:
    1. Stsadm –o installfeature –name custommasterpage
    2. I always run an IIS reset as a matter of practice after I have done anything using stsadm.




Provided that your fetaure has installed correctly when you go to your SharePoint site and navigate to the Site Collection Features link in your Adminitrative UI you should see “Custom Master Pages” as one of your features. Click the “Activate” button to activate the feature (you could do this using stsadm as well if you wanted to).


After the fetaure has been activated go back to site settings and then click on Master page. Click the drop down and you should now see MyCustom.master as an option. Set both the Site Master and System Master pages to MyCustom.master and click “OK”.


Navigate back to the main page of your site and you should now see your custom navigation.

Navigation before our changes


Navigation after our changes


And that’s all there is to it. Now someone is going to say that this isn’t really a “non-developer” solution, I would argue that to a certain extent. It’s just my opinion but every SharePoint Administrator should have the ability to write some basic XML and that’s really all we have done here. One note; don’t forget XML IS CASE SENSITIVE and are the cause of most of the errors I saw when working through this solution.

Now, is this the right solution for you? Well, I think the answer there is the standard SharePoint answer when you’re taking about capabilities or requirement solutions; “It all depends”. I think that for a small to medium environment that this solution would work well. If you’re managing a large environment that has several hundred site collections and/or sites I would strongly suggest you look into the solution that Peter covers in his article. My requirement was complicated by the fact that I am not allows to take code, scripts or any kind of .NET code, off the internet and implement it without going through a long drawn out vetting process. Add to that my obvious lack of programming skills and you see what I came up with.

I hope you’ve found this solution at least interesting and hopefully usefull. If you have any questions please don’t hesitate to ask!

As promised here is a link to a .zip file that has the custom master page, my feature files, the mainMenu.sitemap file and a copy of my web.config. While you can add my custom master page to your implementation don’t try to replace your web.config with mine. Use mine as a reference.

Consistent Navigation Files

Until the next time…

Guest Author: Jay Simcox
The SharePoint Mechanic

Jay Simcox is a SharePoint Architect/Administrator currently disguised as a “Programmer III” for his current employer. Jay has been supporting and managing Microsoft technologies for 10 years with the focus of the last 7 years being SharePoint. With his background in end user training, support and network administration Jay focuses on finding those “no-code” solutions that all “Non-Developers” working with the SharePoint platform crave, developing and providing training for his end user community and sharing his knowledge with as many as he can.

 

Please Join the Discussion

One Response to “SharePoint: Implementing a Custom Navigation Scheme across Multiple Site Collections for the “Non-Developer””
  1. Becky Lash says:

    Great article! Thanks, Jay!


Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!