ASP.NET MVC 2 RoutingEngineSiteMapProvider
July 13, 2010 Leave a comment
Continuing my thought on RoutingEngineSiteMapProvider, I worked with Rob Seder on Sunday for a bit
I was thinking of Maarten Balliau’s solution on CodePlex to a MVCSiteMapProvider and was wondering if there is an easier way. We tried inheriting from StaticSiteMapProvider and copy/pasting the code from XmlSiteMapProvider and re-writing it(like Maarten did), created our own implementation for the SiteMapProvider, and then giving up.
That afternoon I then looked at inheriting from XMLSiteMapProvider and intercepting the NodeCreation to plug in a MvcSiteMapNode. I just created a basic node like so:
public MvcSiteMapNode(SiteMapProvider provider, string key, string url, string title, string description, IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys, string implicitResourceKey):
base(provider, key, url, title, description,roles,attributes,explicitResourceKeys,implicitResourceKey)
{
}
public string Controller { get; set; }
public string Action { get; set; }
The rest of the constructiors were omitted for brevity
I then tried to intercept the call in BuildSiteMap method.
public class RoutingEngineSiteMapProvider: XmlSiteMapProvider
{
public override SiteMapNode BuildSiteMap()
{
SiteMapNode siteMapNode = base.BuildSiteMap();
MvcSiteMapNode mvcSiteMapNode = ConvertSiteMapNodeIntoMvcSiteMapNode(siteMapNode);
return mvcSiteMapNode;
}
private MvcSiteMapNode ConvertSiteMapNodeIntoMvcSiteMapNode(SiteMapNode siteMapNode)
{
MvcSiteMapNode mvcSiteMapNode = new MvcSiteMapNode(siteMapNode.Provider,siteMapNode.Key,
siteMapNode.Url,siteMapNode.Title, siteMapNode.Description);
mvcSiteMapNode.Controller = "Test Controller";
mvcSiteMapNode.Action = "Test Action";
return mvcSiteMapNode;
}
}
Surprisingly, it worked. However, when I went to add a line to check on the nodes themselves in BuildSiteMapNode() like this:
int counter = mvcSiteMapNode.ChildNodes.Count;
Things went bad – Stack Overflow. I was in recursive hell.
I then tried to intercept AddNode like this:
protected override void AddNode(SiteMapNode node)
{
base.AddNode(node);
}
The problem is that this method is not called when I spun up the site.
Grrrr… I am out of patience on this. Looking at the code in Reflector makes me appreciate best practices all that more. Node6 Microsoft, really? What happens if there is a 7th level node? No exception is thrown.
The last thing I can think of is to copy/paste the code in BuildSiteMap() and then getting rid of the XMLReader completely. However, this would be a mucho breaking change because the method violates the Open/Closed Principle and the IoC tenant and I really don’t have the time to track down all of the dangling dependencies in this API.