When implementing solutions for Microsoft Office SharePoint Server 2007 Publishing (WCMS) sometimes you have to implement a custom navigation. Therefore the object model offers
- Microsoft.SharePoint.Navigation
- Microsoft.SharePoint.Publishing.Navigation
which can be found at:
- Microsoft.SharePoint.dll
- Microsoft.SharePoint.Publishing.dll
SharePoint 2007 Publishing Navigation
Basics
If you create a Publishing site you can modify the navigation as shown in the following pictures:
While creating a publishing site the "Portal Navigation Properties" feature is called. You can find the call of the feature in one of the different onet.xml files used for Publishing. Please note that there is more than one Publishing site template and site definition.
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates\PUBLISHING\XML\onet.xml
<Feature ID="541F5F57-C847-4e16-B59A-B31E90E6F9EA">
<!-- Per-Web Portal Navigation Properties-->
<Properties xmlns="http://schemas.microsoft.com/sharepoint/">
<Property Key="InheritGlobalNavigation" Value="true"/>
<Property Key="ShowSiblings" Value="true"/>
<Property Key="IncludeSubSites" Value="true"/>
</Properties>
</Feature>
As you can see there a properties like "ShowSiblings" you can set during the call. The "Portal Navigation Properties" feature is stored at the following location:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\NavigationProperties\feature.xml
<Feature Id="541F5F57-C847-4e16-B59A-B31E90E6F9EA"
Title="Portal Navigation Properties"
Description="Set per-site navigation properties."
Version="12.0.0.0"
Scope="Web"
Hidden="TRUE"
ReceiverAssembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
ReceiverClass="Microsoft.SharePoint.Publishing.NavigationFeatureHandler"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="NavigationSiteSettings.xml"/>
</ElementManifests>
</Feature>
Changing the properties in onet.xml affects the settings. Please note: It is not recommended to change out of the box files. If you want to test it you do an iisreset in order to make sure the changes apply when you create a new publishing site.
Microsoft.SharePoint.Navigation
Programmatically accessing current navigation in SharePoint Publishing
There are different ways to access the current navigation. The namespace
using Microsoft.SharePoint.Navigation;
offers objects like SPNavigationNodeCollection or SPNavigationNode. I tried it this way but it didn't work for me and my scenario.
if (PublishingWeb.IsPublishingWeb(ElevatedSite))
{
PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(ElevatedSite);
SPNavigationNodeCollection nodeColl = pubWeb.CurrentNavigationNodes;
foreach (SPNavigationNode node in nodeColl)
{
//The following statement allways returns true
if (node.IsVisible)
{ }
//The object will be null
object test = node.Properties["vti_nonnavpage"];
}
}
First of all I had to modify the navigation at the publishing site before it showed up in the nodeColl. Second it is not possible the determine if a site or page is hidden because the property "vti_nonnavpage" is not in the property bag of the SPNavigationNode "node" and therefore the getter of property "IsVisible" always returns true. The getter is implemented to return true if it can't find the property. Because of that I tried the PortalSiteMapProvider.
Microsoft.SharePoint.Publishing.Navigation
Programmatically accessing current navigation in SharePoint Publishing with the ProtalSiteMapProvider
You can find the PortalSiteMapProvider in the namespace
using Microsoft.SharePoint.Publishing.Navigation;
In order to get the current navigation you can use the following code:
PortalSiteMapProvider map = new PortalSiteMapProvider();
SiteMapNodeCollection nodeColl = map.CurrentNode.ChildNodes;
foreach (SiteMapNode childNode in nodeColl)
{ //childNode.Title;
//childNode.Key;
//childNode.Url;
}
This code returns a sorted list without the navigation nodes which are hided. You can also access a certain node by using the method FindSiteMapNode with an Url as the parameter.
PortalSiteMapProvider map = new PortalSiteMapProvider();
SiteMapNode node = map.FindSiteMapNode("/PressReleases");
SiteMapNodeCollection nodeColl = node.ChildNodes;
foreach (SiteMapNode childNode in nodeColl)
{ //Your code...
}
For me and my scenario the PortalSiteMapProvider was the way to go. And: You can avoid the problems when using the IsVisible property.
That's it for today... ;)