SiteMapProvider.CurrentNode isn't aware of default.aspx documents in webfolders

The Problem

I think the 'default document' option in IIS is a great way to get clean url's without those .aspx extensions. So instead of calling the url 'http://www.mysite.com/news/default.aspx', you could also call 'http://www.mysite.com/news', which will get you to the same page. This is because IIS finds the default document 'default.aspx' in the news folder.

However, the default SiteMapProvider in ASP.NET 2.0 isn't aware of IIS's default documents, and won't highlight the selected node in a Menu or TreeView contol. Take a look at this xml siteMap file; it will result in links to /default.aspx and /news/default.aspx, but the selected node in my Menu won't be highlighted because the url of the siteMapNode and the request's url don't match:

<?xml version="1.0" encoding="utf-8"?>
<
siteMap
>
  <
siteMapNode title="Home" url="~"
>
    <
siteMapNode title="News" url="~/news"
/>
  </
siteMapNode
>
</
siteMap>

The Solution

Luckily for me, ASP.NET 2.0 has a provider model for the SiteMaps. This means I've just got to override the CurrentNode property of the default XmlSiteMapProvider and add extra logic for recognizing default documents. Take a look at the code of my FolderAware_XmlSiteMapProvider:

using System;
using System.Web;

class FolderAware_XmlSiteMapProvider : XmlSiteMapProvider
{
 
public override SiteMapNode
CurrentNode
  {
   
get
   
{
     
// first let the base resolve the current node
     
SiteMapNode currentNode = base.CurrentNode;
     
     
if (currentNode == null)
     
{
       
// now check if a node exists that's pointing to a folder, and current
        // RawUrl maps to the folder's default document (default.aspx)
       
HttpContext context = HttpContext.Current;
       
if (context != null)
       
{
          string text = context.Request.RawUrl.ToLowerInvariant();
          int index = text.IndexOf("/default.aspx");
          if (index != -1)
          {
            currentNode = FindSiteMapNode(text.Substring(0, index));
            if (currentNode != null && !currentNode.IsAccessibleToUser(context))
            {
              currentNode =
null;
            }
          }
        }
      }
      return currentNode;
    }
  }
}

For your webapplication to use this new FolderAware_XmlSiteMapProvider, you've got to define it in your web.config:

<siteMap defaultProvider="FolderAware_XmlSiteMapProvider">
 
<
providers>
   
<
clear/>
   
<
add siteMapFile="web.sitemap" name="FolderAware_XmlSiteMapProvider" type="FolderAware_XmlSiteMapProvider" />
 
</
providers>
</
siteMap>

...and now the Menu, TreeView and BreadCrumbs contols will highlight the currently selected page even if a request to a webfolder was made!

No Comments