I'm trying to write a custom navigation provider for SharePoint 2010. Later it should be able to distinguish between two different web templates so that sites with one template are only shown in the current navigation on the left and that other sites with another web template are only shown in the top navigation bar.
For this purpose I created a very simple navprovider following this tutorial:
http://msdn.microsoft.com/en-us/library/cc789625(v=office.14).aspx
My class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Navigation;
using System.Web;
using System.Web.UI.WebControls;
using System.Configuration;
namespace xyz.SharePoint
{
public class PortalNavProvider: PortalSiteMapProvider
{
public override SiteMapNodeCollection GetChildNodes(System.Web.SiteMapNode node)
{
PortalSiteMapNode pNode = node as PortalSiteMapNode;
if (pNode != null)
{
if (pNode.Type == NodeTypes.Area)
{
SiteMapNodeCollection nodeColl = base.GetChildNodes(pNode);
SiteMapNode childNode = new SiteMapNode(this, "<http://www.microsoft.com>", "<http://www.microsoft.com>", "Microsoft");
SiteMapNode childNode1 = new SiteMapNode(this, "<http://support.microsoft.com>", "<http://support.microsoft.com>", "Support");
nodeColl.Add(childNode);
SiteMapNodeCollection test = new SiteMapNodeCollection();
test.Add(childNode1);
childNode.ChildNodes = test;
return nodeColl;
}
else
return base.GetChildNodes(pNode);
}
else
return new SiteMapNodeCollection();
}
}
}
It doesn't do anything else than the tutorial so far, because I simply wanted to test this thing at first. Then I copied the dll to \inetpub\wwwroot\wss\VirtualDirectories[Web-App-Name_app_bin (I also tried \14\BIN but didn't change anything) and edited the web.config and added:
<siteMap defaultProvider="CurrentNavigation" enabled="true">
<providers>
<add name="MyCustomNavigationProvider" type="xyz.SharePoint.PortalNavProvider, xyz.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=07c8018bfe42d33f" NavigationType="Global" />
</providers>
</siteMap><trust level="Full" originUrl="" />
The custom navigation provider should be included in a custom masterpage - not in the v4.master. Because of that I added the provided section to the mustom masterpage:
<SharePoint:AspMenu
ID="TopNavigationMenu"
Runat="server"
DataSourceID="topSiteMap1"
EnableViewState="false"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
Orientation="Horizontal"
StaticDisplayLevels="1"
MaximumDynamicDisplayLevels="3"
DynamicHorizontalOffset="0"
StaticPopoutImageUrl="/_layouts/images/menudark.gif"
StaticPopoutImageTextFormatString=""
DynamicHoverStyle-BackColor="#CBE3F0"
SkipLinkText=""
StaticSubMenuIndent="0"
CssClass="ms-topNavContainer">
<StaticMenuStyle/>
<StaticMenuItemStyle CssClass="ms-topnav" ItemSpacing="0px"/>
<StaticSelectedStyle CssClass="ms-topnavselected" />
<StaticHoverStyle CssClass="ms-topNavHover" />
<DynamicMenuStyle BackColor="#F2F3F4" BorderColor="#A7B4CE"
BorderWidth="1px"/>
<DynamicMenuItemStyle CssClass="ms-topNavFlyOuts"/>
<DynamicHoverStyle CssClass="ms-topNavFlyOutsHover"/>
<DynamicSelectedStyle CssClass="ms-topNavFlyOutsSelected"/>
</SharePoint:AspMenu>
<asp:SiteMapDataSource
ShowStartingNode="False"
SiteMapProvider="MyCustomNavigationProvider"
id="topSiteMap1"
runat="server"
StartFromCurrentNode="true"/>
I tried that via Site Actions -> edit with SharePoint Designer and opened the masterpage, but that didn't work. So I tried to edit the masterpage in the solution it belongs to and deployed it again.
At the moment I get the following error if I try to open the site:
The DataSourceID of 'TopNavigationMenuV4' must be the ID of a control of type IHierarchicalDataSource. A control with ID 'topSiteMap' could not be found.
Several things are confusing me at this point. After deploying everything new the site usually uses the standard masterpages at first and I have to change that to the custom masterpage. So why does the site throw that error if the changes are in the custom masterpage?
Besides, in the custom masterpage there is this part:
<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>
So the SiteMapDataSource "topSiteMap" IS there and worked before I added my nav provider. I thought okay maybe there shouldn't be two of them and put the part shown above into a comment. Didn't change anything either.
Does anyone have an idea where the problem could be?
Edit:
I found something else in the ULS logs. Besides the error message, I already posted, there is this one:
DelegateControl: Exception thrown while adding control 'Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapDataSourceSwitch': Could not load type 'xyz.SharePoint.PortalNavProvider' from assembly 'xyz.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=07c8018bfe42d33f'. (C:\inetpub\wwwroot\wss\VirtualDirectories\Web App-80\web.config line 434)
Edit 2:
Okay now I'm completely confused. I used the back button and now the site loads, with the custom masterpage applied. But when I click on site actions -> site settings, I get an empty site
But even when the site loads, when I click the back button of the browser, the same errors appear in the ULS log.
Edit 3:
Somehow I "resolved" the error mentioned above, though I'm not quite sure. Now I'm getting another error and I hope that someone can help me at least with this one.
But first to the previous error: I think it occured, because I was editing the web.config manually and did something wrong. I read that simply one character at the wrong place in the web.config could cause this error. So I removed my changes and put them back in, but carefully. And indeed, the error was gone.
But that is the surpirse I got... a new error of course:
System.TypeLoadException: Could not load type 'xyz.SharePoint.PortalNavProvider' from assembly 'xyz.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=07c8018bfe42d33f'.
at System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
at System.Web.Compilation.BuildManager.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
at System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, XmlNode node, Boolean checkAptcaBit, Boolean ignoreCase)
But still... I have no idea how to handle this one