Click here to Skip to main content
15,880,392 members
Articles / Web Development / ASP.NET
Article

A Better SiteMapResolve

Rate me:
Please Sign up or sign in to vote.
4.83/5 (12 votes)
1 Mar 20063 min read 87.5K   882   52   15
Describes how to create a more useful SiteMapResolve event.

Introduction

I've been working on an ASP.NET 2.0 website recently, and have used the new sitemap features to implement menu and breadcrumb features. However, I had need to dynamically modify the sitemap structure for a specific page.

Others who have tried this will likely be aware of the SiteMap.SiteMapResolve event, which can be used to dynamically construct a sitemap node. However, this event has a rather annoying design flaw - it is static. As such, attaching an event handler to it will result in that handler being called on every request (actually, for every request where the SiteMap.CurrentNode property is accessed).

This article presents a base class for ASP.NET 2.0 pages that provides a page-specific SiteMapResolve event. Pages that inherit from this base class can simply hook into this event and freely modify the sitemap structure knowing that these changes will only affect the current request for that page.

Using the code

Before you go any further, run the example project and take particular note of the following:

  • Pages such as "Contact Us" and "FAQs" are listed in the sitemap file.
  • The NewsItem.aspx page is not listed in the sitemap file. Therefore, it does not appear in the menu. There are links on the home page to three news items, which is the easiest way to get to the NewsItem.aspx page.
  • When you view a news item, an intuitive breadcrumb is displayed - this breadcrumb is a result of dynamically constructed sitemap nodes.

The most important type is the PageBase class. This class inherits from System.Web.UI.Page and adds a SiteMapResolve event that fires only for that page. To use the class, just declare your page to inherit from it as follows:

C#
public partial class NewsItem : Support.PageBase

Once you've inherited from PageBase, you can hook into the SiteMapResolve event in the usual fashion:

C#
protected override SiteMapNode OnSiteMapResolve(SiteMapResolveEventArgs e)
{
    //construct and return your custom SiteMapNode 
    //here - see download for example code
}

Above, I mentioned that the PageBase.SiteMapResolve event fires only for the specific page in which it is handled. That's not entirely accurate. The PageBase class uses a helper method called IsSamePage to determine whether the event should fire. By default, this method returns true if the requests map to the same physical path and have the same query string. This will be sufficient in most cases, but the method can be overridden and customized if necessary.

It's interesting to note that the default implementation of IsSamePage does not actually differentiate between separate instances of pages. That is, if multiple requests for the same page are processed concurrently, you may end up handling the event on behalf of another instance of your page. This won't matter as long as your sitemap structure is based entirely on the information taken from the query string. That's because different query strings will result in IsSamePage returning false and, therefore, the event won't fire.

If your handling of SiteMapResolve relies on some other information, be sure to override IsSamePage accordingly. For example, if you rely on session information to construct your sitemap structure, you could override IsSamePage as follows:

C#
protected virtual bool IsSamePage(HttpContext context1, HttpContext context2)
{
    if (base.IsSamePage(context1, context2))
    {
        return context1.Session["myKey"] == context2.Session["myKey"];
    }
    
    return false;
}

With this override in place, the PageBase.SiteMapResolve event will only fire if:

  • The request is for the same physical file as the current page.
  • The request has the same query string as the current page.
  • The session value with key "myKey" matches in both sessions.

Summary

The code presented in this article will allow you to more easily construct a dynamic sitemap structure in your ASP.NET 2.0 pages. Feel free to copy the PageBase code into your own project, and modify it if necessary. You may already have a base page in place for your project, in which case you can simply copy the relevant code into your base page.

History

  • 1st of March, 2006: Initial revision.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVB.NET Example Pin
pmlarlfs11-Sep-08 10:25
pmlarlfs11-Sep-08 10:25 
Generaldifferent approach proposal Pin
wzychla29-Apr-08 23:29
wzychla29-Apr-08 23:29 
GeneralOnly works about 90% of the time on a busy site Pin
jgd1234521-Apr-08 5:44
jgd1234521-Apr-08 5:44 
QuestionRe: Only works about 90% of the time on a busy site Pin
Mr. McBoinknuts13-Oct-08 9:07
Mr. McBoinknuts13-Oct-08 9:07 
GeneralDownload link is broken.. Pin
Cihan16-Dec-07 16:32
Cihan16-Dec-07 16:32 
Generalvb version Pin
auxcom13-Dec-07 1:15
auxcom13-Dec-07 1:15 
GeneralPageBase and Resolve event vs override Pin
AliasElias9-Aug-07 4:43
AliasElias9-Aug-07 4:43 
GeneralRe: PageBase and Resolve event vs override Pin
Kent Boogaart9-Aug-07 13:48
Kent Boogaart9-Aug-07 13:48 
Generalsitemapresolve VB call Pin
quineman12-Apr-07 22:52
quineman12-Apr-07 22:52 
Put support.dll in you bin directory and call the method like that :

Partial Class test_siteMapResolve
'Inherits System.Web.UI.Page
Inherits Support.PageBase

Protected Overrides Function OnSiteMapResolve(ByVal e As SiteMapResolveEventArgs) As SiteMapNode

Dim homeNode As SiteMapNode = SiteMap.RootNode.Clone
homeNode.ChildNodes = New SiteMapNodeCollection
Dim newsNode As New SiteMapNode(e.Provider, Guid.NewGuid.ToString)
newsNode.ChildNodes = New SiteMapNodeCollection
newsNode.Title = "News"
homeNode.ChildNodes.Add(newsNode)
newsNode.ParentNode = homeNode
Dim newsItemNode As New SiteMapNode(e.Provider, Guid.NewGuid.ToString)
newsItemNode.Title = "Ma child new"
newsNode.ChildNodes.Add(newsItemNode)
newsItemNode.ParentNode = newsNode
Return newsItemNode


End Function

End Class
GeneralUse Context.CurrentHandler Pin
chadly694-Dec-06 19:24
chadly694-Dec-06 19:24 
Generalthanks a lot Pin
Oskars Podans14-Jun-06 21:48
Oskars Podans14-Jun-06 21:48 
GeneralRe: thanks a lot Pin
Kent Boogaart14-Jun-06 22:32
Kent Boogaart14-Jun-06 22:32 
QuestionVB version Pin
trancehead13-Mar-06 22:07
trancehead13-Mar-06 22:07 
AnswerRe: VB version Pin
Kent Boogaart13-Mar-06 22:22
Kent Boogaart13-Mar-06 22:22 
GeneralRe: VB version Pin
millen20-Aug-06 15:56
millen20-Aug-06 15:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.