Dionoid

ALL WEB MUST SCALE!
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!

Published Friday, June 10, 2005 11:39 AM by Dr.NETjes

Comments

# re: SiteMapProvider.CurrentNode isn't aware of default.aspx documents in webfolders@ Wednesday, June 15, 2005 2:41 PM

Nice solution! Would there be an easy way to check what the default documents would actually be (I think this is configured in the IIS metabase). Suppose you have a index.htm in your folder, then the default.aspx file would not map to the ~/news url.

Teun

Leave a Comment

(required) 
(required) 
(optional)
(required)