I recently was trying to enable the top nav bar to be a drop down menu of all of the sub sites. I found this article http://sharingpoint.blogspot.com/2007/02/wss-v3-drop-down-menus-in-team-sites.html which told me everything I needed to know. Instead of modifying the default.master and the TopNavBar.ascx (for the application.master) to change the SPNavigationProvider to SPSiteMapProvider, I decided I wanted each teamsite to have the option and I’m reluctant from changing SharePoint system files (see http://www.graphicalwonder.com/?p=532), so I put this part into a feature. Here’s my code below:
The first file is Feature.xml
<Feature Id="22b94164-5348-11dc-8314-0800200c9a66" Title="All Sites in Site Collection Navigation" Description="Enable all sites in the site collection top navigation bar." Version="126.96.36.199" Scope="Web" Hidden="false" DefaultResourceFile="core" xmlns="http://schemas.microsoft.com/sharepoint/"> <ElementManifests> <ElementManifest Location="NavigationSiteSettings.xml"/> </ElementManifests> </Feature>
The second file is NavigationSiteSettings.xml
<Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <!-- Top Nav --> <Control Sequence="25" Id="TopNavigationDataSource" ControlClass="System.Web.UI.WebControls.SiteMapDataSource" ControlAssembly="System.Web, version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <Property Name="ID">topSiteMap</Property> <Property Name="SiteMapProvider">SPSiteMapProvider</Property> <Property Name="ShowStartingNode">true</Property> </Control> <HideCustomAction Id="TopNav" HideActionId="TopNav" GroupId="Customization" Location="Microsoft.SharePoint.SiteSettings" /> </Elements>
I still needed to modify the default.master and TopNavBar.ascx (you don’t need to edit the TopNavBar.ascx if you are implementing my Using your SharePoint site Master Page on all application pages) so that more than one level is shown. I haven’t figured out a way around that part yet. Does anyone else know a way to override the SharePoint.AspMenu control?
Update (09/21/07): I have since found out that apparently the SPSiteMapProvider relies on the user having permissions to view the top-level site in the site collection. If the user does not have access to this top-level site, then they will be prompted for authentication and won’t be able to access the site. Using Reflector I was able to find the code where they are finding the top-level site without checking for permissions first.
I ended up having to write my own SiteMapProvider that did the correct security checking and trimming while still allowing access to the site.
On a side note, while I was looking into this issue, I also noticed that the Global Breadcrumbs (which also uses the SPSiteMapProvider) doesn’t do security trimming. So I wrote a SiteMapProvider for the Global Breadcrumbs as well that did security trimming. There doesn’t seem to be a delegate control for the Global Breadcrumbs like there is for the top nav so I couldn’t write a feature to override the default. So I decided to just change my default.master and in combination with Using your SharePoint site Master Page on all application pages will use my custom SiteMapProvider for the Global Breadcrumbs.
Update (05/19/08): Some people have asked for the source code of my custom site map providers. You can download my latest files below:
FYI, this may not be the most efficient code and I have noticed some caching issues with it sometimes. Other than that it seems to work great.