Implementing a custom SiteMapProvider
Thursday, January 26, 2006 2:50:36 PM
|
Rate this Content
|
|
0 Votes
|
For mojoPortal I needed to implement a custom SiteMapProvider to use the new ASP.NET 2.0 Menu and treeview controls and the built in SiteMapPath control which provides breadcrumbs. Since mojoPortal supports multiple database platforms (MS SQL, MySQL, PostgreSQL, and more recently SQLite thanks to Joseph Hill) I needed a solution that would work with all of them.
One approach would be to make a MSSqlSiteMapProvider (there is already one out there you can use), a MySqlSiteMapProvider, a PostgreSqlSiteMapProvider and so on. But since I already have a SiteSettings business object which has a PageSettings collection it made sense to implement my mojoSiteMapProvider using these objects which are already abstracted above the data services facade. For anyone else who might already have some business objects reperesenting the page hierarchy of their site I thought I would post this example:
using System;
using System.IO;
using System.Web;
using System.Data.SqlClient;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Web.Configuration;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Security.Permissions;
using System.Data.Common;
using System.Data;
using System.Web.Caching;
using mojoPortal.Business;
namespace mojoPortal.Web
{
/// <summary>
/// Author: Joe Audette
/// Created: 1/21/2006
/// Last Modified: 1/23/2006
///
/// </summary>
public class mojoSiteMapProvider : StaticSiteMapProvider
{
private const string cacheDependencyName = "siteMapCacheDependency";
private readonly object objLock = new object();
private SiteMapNode rootNode;
private Dictionary<int, SiteMapNode> nodes = new Dictionary<int, SiteMapNode>(16);
protected SiteSettings siteSettings;
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
{
throw new ArgumentNullException("config");
}
if (String.IsNullOrEmpty(name))
{
name = "mojoSiteMapProvider";
}
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "mojoPortal site map provider");
}
base.Initialize(name, config);
}
public override SiteMapNode BuildSiteMap()
{
if (rootNode != null)
{
return rootNode;
}
lock (objLock)
{
siteSettings = SiteSettings.GetCurrent();
if (siteSettings != null)
{
rootNode = CreateSiteMapNode((PageSettings)siteSettings.Pages[0], -1);
for (int i = 0; i < siteSettings.Pages.Count; i++)
{
PageSettings page = (PageSettings)siteSettings.Pages[i];
AddNode(CreateSiteMapNode(page, i), GetParentNode(page));
}
}
}
CacheDependency cacheDependency = new CacheDependency(
SiteUtils.GetPathToSiteMapCacheDependencyFile());
HttpRuntime.Cache.Insert(
cacheDependencyName,
new object(),
cacheDependency,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
new CacheItemRemovedCallback(OnSiteMapChanged));
return rootNode;
}
private SiteMapNode CreateSiteMapNode(PageSettings page, int pageIndex)
{
string[] rolelist = null;
if (!String.IsNullOrEmpty(page.AuthorizedRoles))
{
rolelist = page.AuthorizedRoles.Split(new char[] { ',', ';' }, 512);
}
string pageUrl;
if (page.UseUrl)
{
pageUrl = page.Url;
}
else
{
if (pageIndex > -1)
{
pageUrl = "~/Default.aspx?pageindex=" + pageIndex.ToString()
+ "&pageid=" + page.PageID.ToString();
}
else
{
pageUrl = "~/Default.aspx?pageid=" + page.PageID.ToString();
}
}
SiteMapNode node = new SiteMapNode(
this,
page.PageID.ToString(),
pageUrl,
page.PageName,
page.PageName,
rolelist, null, null, null);
if(!this.nodes.ContainsKey(page.PageID))
{
nodes.Add(page.PageID, node);
}
return node;
}
private SiteMapNode GetParentNode(PageSettings page)
{
if (page.ParentID <= -1)
{
return this.rootNode;
}
return nodes[page.ParentID];
}
protected override SiteMapNode GetRootNodeCore()
{
BuildSiteMap();
return rootNode;
}
protected override void Clear()
{
lock (objLock)
{
this.rootNode = null;
this.nodes.Clear();
base.Clear();
}
}
public void OnSiteMapChanged(string key, object item, CacheItemRemovedReason reason)
{
Clear();
}
}
}