When building a left-hand navigation control using a Web.Sitemap file and the default .NET2 sitemap provider, I hit an annoying snag. I wanted my navigation to look like this:

Home
- Welcome
- News
- About

In terms of pages, it would look like this:

Home.aspx
- Welcome.aspx
- News.aspx
- About.aspx

So far so easy. I just wrote a simple routine in the Page.Load of my master page that gets SiteMap.CurrentNode and then iterates back to the root node, rendering the menu as it goes via a repeater:

        if(SiteMap.CurrentNode != null)
        {
            SiteMapNode tempNode = SiteMap.CurrentNode;

            if (tempNode == null)
            {
                return;
            }

            if(tempNode == SiteMap.RootNode) return;

            while(!tempNode.ParentNode.Equals(SiteMap.RootNode))
            {
                tempNode = tempNode.ParentNode;
            }

            if(tempNode.ChildNodes.Count != 0)
            {
                ContextMenuRepeater.DataSource = tempNode.ChildNodes;
                ContextMenuRepeater.DataBind();
            }
        }

The repeater then looks like this:

<li>
    <asp:HyperLink runat="server" ID="ContextMenuHyperLink" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink></li>

Well that worked fine, until I came to put some News Articles in. You see, the news articles used a page called NewsArticle.aspx. As that wasn't in the sitemap, my code returned null when it tried to get SiteMap.CurrentNode. Therefore, I couldn't iterate my tree so my menu was appearing blank. As if to make things even trickier, the URL contained a QueryString, e.g. NewsArticle.aspx?article=11.

Thankfully, the Web.Sitemap and provider is kinda clever enough that if I create a node in the Web.Sitemap for NewsArticle.aspx then it's intelligent enough to ignore the QueryString (although note that you CAN include the QueryString in a Web.Sitemap as well, so if for example you were using a CMS whereby every page was on a querystring, it could cater for it, e.g. cms/default.aspx?pageid=1234).

So I put an entry in the Web.Sitemap and hey presto, I got my menu back. Only problem was, I was also getting an ugly 'News Article' item appearing in my navigation. I only wanted to go down to the 'News' level and whilst it might be fine for a breadcrumb trail, my navigation was messed up. I tried putting my own attributes on (e.g. 'visible') and whilst the XML didn't complain, the Sitemap provider didn't know what I was on about. I knew that I could start overwriting methods and events to sort it, or even write my own provider, but I wanted a quick and easy solution because all I was doing was writing a prototype.

Quick and dirty solution then. I was writing out the Url and Title values from the Web.Sitemap into my navigation and wasn't using Description for any reason. I therefore set the Description of the NewsArticle entry to 'DO NOT DISPLAY', and changed my repeater to read like so:

><li <%#((string)DataBinder.Eval(Container.DataItem, "Description")) == "DO NOT DISPLAY" ? "style=\"display:none\"" : "TRUE"%>>
    <asp:HyperLink runat="server" ID="ContextMenuHyperLink" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink></li>

And that worked. It hides the NewsArticle from my menu but because it's only a display thing on the navigation, it still gets picked up as SiteMap.CurrentNode and works correctly. I also use the Title to set the title of the web browser.

Hope this quick and dirty fix can help someone in a pinch. If there's any other easymode solutions out there let me know.

 


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Wednesday, December 19, 2007 10:52 AM | in .NET/C#

Comments

Gravatar
# re: Web.Sitemap and QueryString
Posted by basil
on 6/16/2008 9:48 AM
If you are using asp:Menu to achieve the above mentioned effect you can handle its MenuItemDataBound event and do something like this (the code uses the trick described in the article)

protected void Menu1_MenuItemDataBound(object sender, MenuEventArgs e)
{
if (((SiteMapNode)e.Item.DataItem).Description == "do_not_display")
{
e.Item.Text = "";
}
}

That successfully prevents a node from being displayed in menu while allowing to have web.sitemap bound menus on 'hidden' pages

Post Comment

Title *
Name *
Email
Url
Comment *  


Please add 7 and 3 and type the answer here: