This is a follow-up post related to my troubles with the SiteMap control and related provider. The original post can be found here
I emailed Scott Guthrie to ask about a solution to the problem. He directed me to Danny Chen who answered my question. It is, in fact, possible to do what I want to do and here's how:
I was onto the right path w/ the SiteMap.SiteMapResolve event. I'm not sure why I was recieving a "Request collection is unavailable" error, but it went away. The code Danny sent me would update the url of the current node and parent node with the current querystring. While this got me started, I wanted to give a little more control to the siteMapNodes in the web.sitemap file to choose which variables, if any, they are reliant on. This is an example of a siteMapNode that relies on a querystring variable to function:

<siteMapNode url="~/hotels/details.aspx" title="Hotel Information" reliantOn="HotelID, UserID" />
The siteMapNode specified above relies on HotelID and UserID, which are variables that would be in the querystring. If they don't exist in the querystring, they are ignored.
The following code is a custom SiteMapProvider that derives from XmlSiteMapProvider.

public class SmartSiteMapProvider : XmlSiteMapProvider
{
public override void Initialize(string name, NameValueCollection attributes)
{
base.Initialize(name, attributes);
this.SiteMapResolve += new SiteMapResolveEventHandler(SmartSiteMapProvider_SiteMapResolve);
}
SiteMapNode SmartSiteMapProvider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)
{
if(SiteMap.CurrentNode == null)
return null;
SiteMapNode temp;
temp = SiteMap.CurrentNode.Clone(true);
Uri u = new Uri(e.Context.Request.Url.ToString());
SiteMapNode tempNode = temp;
while(tempNode != null)
{
string qs = GetReliance(tempNode, e.Context);
if(qs != null)
if(tempNode != null)
tempNode.Url += qs;
tempNode = tempNode.ParentNode;
}
return temp;
}
private string GetReliance(SiteMapNode node, HttpContext context)
{
if(node["reliantOn"] == null)
return null;
NameValueCollection values = new NameValueCollection();
string[] vars = node["reliantOn"].Split(",".ToCharArray());
foreach(string s in vars)
{
string var = s.Trim();
if(context.Request.QueryString[var] == null)
continue;
values.Add(var, context.Request.QueryString[var]);
}
if(values.Count == 0)
return null;
return NameValueCollectionToString(values);
}
private string NameValueCollectionToString(NameValueCollection col)
{
string[] parts = new string[col.Count];
string[] keys = col.AllKeys;
for(int i = 0; i < keys.Length; i++)
parts[i] = keys[i] + "=" + col[keys[i]];
string url = "?" + String.Join("&", parts);
return url;
}
}
Still not sure why I get a StackOverflowException when I try to access the ChildNodes property of the root node when I override the BuildSiteMap method, but now that I have this working, I care not.
Updated 12/8/2005 1:05:10 PM
Danny Chen from Microsoft was nice enough to explain the reason behind the stack overflow expcetion I was experiencing.
Click here to read that post.