ASP.NET 2.0 has a really cool feature, actually ASP.NET 1.x supported this but I never came across it for some reason. But while coding my new site with ASP.NET 2.0 using all the new features, I came across it. Its also posted on MSDN, in case your curious.
Here's the problem I was facing. For my site I am using the new PageControl class which saves a bunch of time which give you the web.sitemap xml file capability:
<
siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url ="~/" title="ElucidWeb" description="ElucidWeb">
<siteMapNode url="~/default.aspx" title="Home" description="Welcome to ElucidWeb Software" />
<siteMapNode url="~/blognews.aspx" title="Blog/News" description="Developer Blogs & Site News" />
<siteMapNode url="~/products/products.aspx" title="Products" description="Products" />
<siteMapNode url="~/projects/projects.aspx" title="Projects" description="Projects" />
<siteMapNode url="~/beta/beta.aspx" title="Beta" description="Beta" />
<siteMapNode url="~/support/support.aspx" title="Support" description="Support" />
<siteMapNode url="~/help/help.aspx" title="Help" description="Help" />
</siteMapNode>
</siteMap>
Mine looks a bit funny cause of the way I have laid it out so that my TreeView and my BreadCrumb control would look, and path correctly. But in any case by using PageControl.GetCurrent() you can retrieve the current URL, which comes in handy! You can also iterate over and query it, etc..
For me I wanted to disconnect the image paths from my UI design so I created an additional XML file that I called SiteImageMap.xml and I put this in my App_code folder for simplicity sake. I wanted this file and my web.sitemap file to be work in unison. Well I ran into a problem getting the images to map relative to the folder they were in, for instance if I was in www.elucidweb.com the images/image.gif worked fine but if i was in www.elucidweb.com/products/ then the URL would point to images/products/image.gif which doesn't exist!
Heres the SiteImageMap.xml file:
<
SiteImageMap>
<SiteImage ID="Home" CurrentImageUrl="~/images/home.gif" TopNavImageUrl="~/images/layout/nav/navheader_home_selected.gif"/>
<SiteImage ID="Blog/News" CurrentImageUrl="~/images/news.gif" TopNavImageUrl="~/images/layout/nav/navheader_blognews_selected.gif" />
<SiteImage ID="Products" CurrentImageUrl="~/images/product.gif" TopNavImageUrl="~/images/layout/nav/navheader_products_selected.gif" />
<SiteImage ID="Projects" CurrentImageUrl="~/images/projects.gif" TopNavImageUrl="~/images/layout/nav/navheader_projects_selected.gif" />
<SiteImage ID="Beta" CurrentImageUrl="~/images/beta.gif" TopNavImageUrl="~/images/layout/nav/navheader_beta_selected.gif" />
<SiteImage ID="Support" CurrentImageUrl="~/images/support.gif" TopNavImageUrl="~/images/layout/nav/navheader_support_selected.gif" />
<SiteImage ID="Help" CurrentImageUrl="~/images/help.gif" TopNavImageUrl="~/images/layout/nav/navheader_help_selected.gif" />
</SiteImageMap>
So to get around the problem of linking my images directly in my UI design I came up with a rather simple class that inherits from Control, by inheriting I get to use the Control.ResolveUrl method which will Map any URL encoded in a special format beginning with "~/", this marks the root of your web application and it resolves the url from that point on, all you do is provide it the information from the root to the location and it will parse it accordingly. Now in my old web design I put this code directly into my HTML like <%= Control.ResolveURL("~/blah/...") %> but this is a much more elagant way of doing it IMHO.
The code for the class:
public class PageControl : Control
{
const string CurrentPageKey = "current_Page"; //specifies the key to use for the cache items...
static HttpContext current = HttpContext.Current;
public void SetCurrentPage(string page)
{
current.Cache[CurrentPageKey] = page;
}
public string GetCurrentPage()
{
return current.Cache[CurrentPageKey].ToString();
}
public string MapCurrentImage()
{
string Url = GetCurrentPage();
string xmlpath = current.Server.MapPath("~/App_Data/SiteImageMap.xml");
XmlDocument doc = new XmlDocument();
doc.Load(xmlpath);
string xpath = String.Format("/SiteImageMap/SiteImage[@ID='{0}']", Url);
string imageURL = doc.SelectSingleNode(xpath).Attributes["CurrentImageUrl"].Value;
return ResolveUrl(imageURL);
}
public string MapTopNavImage()
{
string Url = GetCurrentPage();
string xmlpath = current.Server.MapPath("~/App_Data/SiteImageMap.xml");
XmlDocument doc = new XmlDocument();
doc.Load(xmlpath);
string xpath = String.Format("/SiteImageMap/SiteImage[@ID='{0}']", Url);
string imageURL = doc.SelectSingleNode(xpath).Attributes["TopNavImageUrl"].Value;
return ResolveUrl(imageURL);
}
}
So thats all there is to it, very very simple but it did take some digging around and testing for me to come up with but in the end its an extremely useful way of doing things. If you like or modify or dislike then go ahead and tell me, would love to hear your comments on it.