Tuesday, August 25, 2009

SiteMapProvider doesn't take QueryString into consideration

I was pretty stoked to find that ASP.NET 2.0 included a new control called SiteMap. This control will display a breadcrumb trail of links as you navigate through your site. By default, the data is loaded from a web.sitemap file that sits in the web app root. Although you can load the data from any source, this is the default and uses the XmlSiteMapProvider provider to populate the data.

This is an example of data found in the web.sitemap file:
Copy code to clipboard in IE or select code for Firefox

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
<siteMapNode url="~/default.aspx" title="Home">
<siteMapNode url="~/hotels/list.aspx" title="Hotel Listings">
<siteMapNode url="~/hotels/details.aspx" title="Hotel Information">
<siteMapNode url="~/hotels/update.aspx" title="Update Hotel"/>
</siteMapNode>
</siteMapNode>
</siteMapNode>
</siteMap>



This works fine if you aren't ever using querystring variables. But let's say when you get down to the details.aspx page, you tag on a HotelID variable to the querystring. Same thing happens when you go deeper into update.aspx.

Your breadcrumb will look like this:

Home > Hotel Listings > Hotel Information > Update Hotel

Given my current url is "update.aspx?HotelID=1234", I should have some way to propagate the current HotelID querystring variable to the other links, if they need it, which details.apx does.

I tried endlessly to get around this. I tried derriving my own class from XmlSiteProvider, but ASP.NET crashes as soon as you mess w/ the child nodes in the BuildSiteMap() method.

I tried binding an event handler to the SiteMap.SiteMapResolve event - but the Request collection is always unavailable at the time when this event is triggered.

I tried to modify the url's of the nodes showing on the screen dynamically, but supid SiteMapNode.Url property is Read-Only - ARGGG!!

It just amazes me that MS didn't see this coming & allow for it in the XML config. They could have added a "incorporate" attribute in the node that allowed you to specify a comma-delimited list of querystring variables that would be needed for that URL to work, like this:

Copy code to clipboard in IE or select code for Firefox

<siteMapNode url="~/hotels/details.aspx" title="Hotel Information" reliantOn="HotelID, UserID">



or give me a way to add in the querystring variables I want to pull from the current context like this:

Copy code to clipboard in IE or select code for Firefox

<siteMapNode url="~/hotels/details.aspx?HotelID={HotelID}" title="Hotel Information">



And the SiteMapProvider would be smart enough to replace the vars in braces w/ the variable from the current querystring.

I never thought getting something so simple to work would be so hard. If anyone has a solution, pony up.

No comments: