Using SiteMap for external links and additional attributes

In a website we are currently developing we are using the WCSF (from the Patterns and Practices group) and we wanted to inject in some links to a few external websites. The WCSF uses a custom SiteMapProvider that is part of its framework. A coworker highlighted how he solved the problem by simply overriding the URL as part of the TreeView (our menu) databound event handler within a master page.

I wasn’t especially happy with this solution since it separated the URL information from the code that created the information in the first place.

Since the problem originated a “not in virtual path” when the sitemap node has a URL that’s external to the application, I decided to route the external links through a redirect page (Redirect.aspx). The other important thing is to use HttpUtility.UrlEncode and HttpUtility.UrlDecode to take care of making the URL suitable for a querystring value.

(Note: don’t use escaped characters in the input string – e.g. +, %2f, etc. since this makes HttpUtility.UrlEncode assume the string is already encoded).

The redirect page is simply this:

if (!String.IsNullOrEmpty(Request.QueryString["url"]))
{
    string url = HttpUtility.UrlDecode(Request.QueryString["url"]);
    Response.Redirect(url);
}
else
{
    Response.Redirect("~/Default.aspx");
}

Then when inserting the SiteMapNodeInfo nodes into the collection I instead formatted the URL with:

string url = String.Format("~/Redirect.aspx?url={0}", HttpUtility.UrlEncode("http://www.myexternallink.com"));

The rest is specific to WCSF SiteMapNodeInfo nodes, but additionally, I wanted the external link to pop-out into a new browser window (target=”_blank”) so we need to pass in NameValueCollection with key/values for all the attributes you want converted in the final SiteMapNode instance (in our case we simply need Target):

NameValueCollection attrs = new NameValueCollection(1);
attrs.Add("Target", "_blank");
SiteMapNodeInfo externalLinkNode = new SiteMapNodeInfo("ExternalLink1", url, "My External Site", "Check out the external site", null, attrs, null, null);

Then as was pointed out earlier, in order to take advantage of those additional attributes within your Menu or TreeView we will have to do so within our master page (or page).

protected void MainMenu_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
    Debug.Assert(e.Node.DataItem != null);
    Debug.Assert(e.Node.DataItem is SiteMapNode);
    e.Node.Target = (e.Node.DataItem as SiteMapNode)["Target"];
}

You could use the same method using additional attributes on the SiteMapNode used to include little images or icon’s (e.g. ImageUrl) next to the menu node.

Hope this helps some lost soul…

Love,
Reddog.


One thought on “Using SiteMap for external links and additional attributes

  1. Thanks for the info. I never would’ve figured out the TreeNodeDataBound part of this puzzle.

Leave a comment