Hi,
Sometimes we need to overwrite the existing navigation provider and write our own provider to get the data from list,db or any other third party application.This post will help you to understand how you can implement the custom navigation provider.
The implementation requires the following steps
1.) Creation of new class which should be inherited from
"PortalSiteMapProvider" class.
2.) Custom provider entry in web.config file
3.) Custom provider reference in master page or user control
Create new Class inherited from "PortalSiteMapProvider"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Publishing.Navigation;
using Microsoft.SharePoint.Publishing;
using System.Web;
using Microsoft.SharePoint;
using System.Security.Permissions;
using Microsoft.SharePoint.Security;
using System.Collections;
namespace XYZ.XYZ
{
//Assign the neccessary security permissions
[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[SharePointPermissionAttribute(SecurityAction.LinkDemand, ObjectModel = true)]
[AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[SharePointPermissionAttribute(SecurityAction.InheritanceDemand, ObjectModel = true)]
public class XYZNavigationProvider : PortalSiteMapProvider
{
//Create the in memory objects for storage and fast retreival
protected SiteMapNodeCollection siteMapNodeColl;
protected ArrayList childParentRelationship;
//These are only the top level nodes that will show in the top nav
protected ArrayList topLevelNodes;
private PortalSiteMapNode rootNode = null;
SiteMapNodeCollection objNodesCollection;
/// Override the initialize method of the superclass
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
try
{
lock (this)
{
if (rootNode != null)
{
return;
}
else
{
// Verify that config isn't null
if (config == null)
throw new ArgumentNullException("config is null");
// Assign the provider a default name if it doesn't have one
if (String.IsNullOrEmpty(name))
name = Constants.NAVIGATION_PROVIDER;
// Add a default "description" attribute to config if the
// attribute doesn’t exist or is empty
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Custom navigation provider");
}
NavigationArea = Convert.ToString(config["description"]);
base.Initialize(name, config);
}
}
}
catch (Exception ex)
{
throw(ex);
}
}
public override SiteMapNode CurrentNode
{
get
{
string currentUrl = FindCurrentUrl();
// Find the SiteMapNode that represents the current page.
SiteMapNode currentNode = FindSiteMapNode(currentUrl);
if (currentNode == null)
{
return base.CurrentNode;
}
return currentNode;
}
}
public override SiteMapNodeCollection GetChildNodes(System.Web.SiteMapNode node)
{
PortalWebSiteMapNode ptlWebSiteMapNode;
SiteMapNodeCollection objSiteMapNodeCollection = default(SiteMapNodeCollection);
try
{
PortalSiteMapNode portalNode = node as PortalSiteMapNode;
if (portalNode != null && portalNode is PortalWebSiteMapNode)
{
ptlWebSiteMapNode = (PortalWebSiteMapNode)portalNode;
if (portalNode.Type == NodeTypes.Area)
{
objSiteMapNodeCollection = ComposeNodes(node, (PortalWebSiteMapNode)portalNode);
}
else
{
objSiteMapNodeCollection = base.GetChildNodes(portalNode);
}
}
else
{
objSiteMapNodeCollection = new SiteMapNodeCollection();
}
}
catch (Exception ex)
{
throw(ex);
}
objNodesCollection = objSiteMapNodeCollection;
return objSiteMapNodeCollection;
}
public virtual SiteMapNodeCollection ComposeNodes(System.Web.SiteMapNode node, PortalWebSiteMapNode ptlWebSiteMapNode)
{
object Nodes;
PortalSiteMapNode RootNode;
SPQuery objSPQuery;
String Query;
SPListItemCollection objItems;
String PageURL;
String Title = String.Empty;
SiteMapNodeCollection nodeColl = new SiteMapNodeCollection();
SPSite currentSite;
SPWeb currentWeb;
SPList objList;
bool isChangePasswordVisible = true;
//The SiteMapNodeCollection which represents the children of this node
SiteMapNodeCollection children = new SiteMapNodeCollection();
PortalSiteMapNode portalNode = node as PortalSiteMapNode;
bool IsNavigationLinkEnable;
if (Nodes != null && Nodes is SiteMapNodeCollection)
{
return ((SiteMapNodeCollection)Nodes);
}
nodeColl = new SiteMapNodeCollection();
currentSite = SPContext.Current.Site;
currentWeb = currentSite.RootWeb;
objList = currentWeb.Lists[Constants.LIST_NAVIGATIONS];
objSPQuery = new SPQuery();
Query = String.Format("
{0}", NavigationArea);
objSPQuery.Query = Query;
objItems = objList.GetItems(objSPQuery);
if (objItems != null && objItems.Count > 0)
{
foreach (SPListItem objItem in objItems)
{
Title = objItem[SPBuiltInFieldId.Title]);
if (!String.IsNullOrEmpty(PageURL))
{
RootNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, PageURL, Title, Title);
}
else
{
RootNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, "#", Title, Title);
}
// Call method to get the child items
GetChildNavigations(objItem.Title, RootNode, objList, ptlWebSiteMapNode);
nodeColl.Add(RootNode);
}
}
}
return nodeColl;
}
void GetChildNavigations(string KeyTitle, PortalSiteMapNode RootNode, SPList objList,PortalWebSiteMapNode ptlWebSiteMapNode)
{
SPQuery objSPQuery;
SPListItemCollection objItems;
PortalSiteMapNode childNode;
bool isChangePasswordVisible = true;
bool IsNavigationLinkEnable;
SiteMapNodeCollection objSiteMapNodeCollection = new SiteMapNodeCollection();
objSPQuery = new SPQuery();
String Title =String.Empty;
String PageURL;
//objSPQuery.Query = String.Format("
{0}", Title);
objSPQuery.Query = String.Format("
{0}", KeyTitle);
objItems = objList.GetItems(objSPQuery);
if (objItems != null && objItems.Count > 0)
{
foreach (SPListItem objItem in objItems)
{
Title = Convert.ToString(objItem[SPBuiltInFieldId.Title]);
if (!String.IsNullOrEmpty(PageURL))
{
childNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, PageURL, Title, Title);
}
else
{
childNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, "#", Title, Title);
}
objSiteMapNodeCollection.Add(childNode);
// Call method again (recursion) to get the child items
GetChildNavigations(objItem.Title, childNode, objList, ptlWebSiteMapNode);
}
}
}
RootNode.ChildNodes = objSiteMapNodeCollection;
}
else
{
return;
}
}
#region Supporting Methods
// Get the URL of the currently displayed page.
private string FindCurrentUrl()
{
try
{
// The current HttpContext.
HttpContext currentContext = HttpContext.Current;
if (currentContext != null)
{
return currentContext.Request.RawUrl;
}
else
{
throw new Exception("HttpContext.Current is Invalid");
}
}
catch (Exception e)
{
throw new NotSupportedException("This provider requires a valid context.", e);
}
}
// Implement the FindSiteMapNode method.
public override SiteMapNode FindSiteMapNode(string rawUrl)
{
// Does the root node match the URL?
if (RootNode.Url == rawUrl)
{
return RootNode;
}
else
{
SiteMapNode candidate = null;
// Retrieve the SiteMapNode that matches the URL.
lock (this)
{
candidate = GetNode(objNodesCollection, rawUrl);
}
return candidate;
}
}
private SiteMapNode GetNode(SiteMapNodeCollection objNodesCollection, string url)
{
SiteMapNode objInnerNode = null;
if (objNodesCollection != null)
{
foreach (SiteMapNode objNode in objNodesCollection)
{
if (objNode.Url == HttpContext.Current.Request.Url.AbsoluteUri)
return objNode;
else if (objNode.HasChildNodes && objNode.ChildNodes.Count > 0)
{
objInnerNode = GetNode(objNode.ChildNodes, url);
if (objInnerNode != null)
{
return objInnerNode;
}
}
}
}
return null;
}
#endregion
}
}
Add entry in web.config
After creating the class, add the entry of the class in web.config file of the site.
Add this entry under the sitemap->provider tag.
< siteMap defaultProvider="CurrentNavigation" enabled="true" >
< providers >
< add name="XYZNavigationProviderTop" description="Custom Provider" type="XYZ.XYZNavigationProvider, XYZ" NavigationType="Current" / >
< /provider >
< /sitemap >
Use the custom navigation provider in the master page
< publishingnavigation:portalsitemapdatasource sitemapprovider="XYZNavigationProviderLeft"
id="XYZNavSiteMap" runat="server" showstartingnode="false"/ >