Skip Navigation Links » Blog » SiteMapPath-Control-and-dynamic
  • SiteMapPath Control and dynamic url based on querystring.

    by

     The SiteMapPath control is really great. If you need breadcrumbs, eg a trail left based on the depth of the pages, this is absolutely a great control. However all is nice when the navigation is defined in your sitemap, this means static url's. But what if you have a dynamic url, maybe its based on querystring's and you want to leave a trail. There is some help in the msdn documentation regarding this, however its not very clear. The reference I am talking about is : http://msdn2.microsoft.com...

    As you can see from the above documentation material, it tells you that if you need this type of functionality then you need to subscribe to the SiteMapResolve event handler of your sitemap. "This event is raised when the CurrentNode property is accessed. This enables the user to implement custom logic when creating a SiteMapNode representation of the currently executing page without requiring a custom provider implementation."

    All good, except I think this event could be documented better. To be honest, I saw the sample code provided with the documentation, and it took a bit of experimentation to actually get it to work the way I wanted. Imagine a simple scenario where you have an initial home page, then two pages within the same physical directory, so to simplify lets look at an example sitemap :
    XML
    
                  
    <xml version="1.0" encoding="utf-8" ?>
    <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
    <siteMapNode url="~/Default.aspx" title="Home">
    <siteMapNode url="~/list.aspx" title="List items" />
    <siteMapNode url="~/details.aspx" title="Details page" />
    <siteMapNode>
    <siteMap>
    Now as you can see, i have 3 pages :
    1. Default.aspx = Home page
    2. list.aspx        = List items
    3. details.aspx  = Details of each item in the list page.
    Now, this is what is going to happen. On default page, i have a link to List.aspx ; List.aspx just displays a list of items and clicking an item in the list should display details on the item. To do this we will be passing the item id in the querystring. This means the parent/child relationship btw list.aspx and details.aspx is a logical relationship, which is related by the id we will be passing in the querystring.

    For this type of relationships a) The SiteMapPath wont pick it up, anddefine a trail, if we do not nest details.aspx in list.aspx, b) Thevalue we will be passing in the querystring is dynamic and in thesitemap we can only define static url's. Its too bad the sitemapsupports localization expressions but not inline codeblocks, a pity anda limitation you have to live with.

    So knowing these two things, we can start by redefining our site to satisfy with the above requirement a) :
    XML
    
                  
    <xml version="1.0" encoding="utf-8" ?>
    <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
    <siteMapNode url="~/Default.aspx" title="Home">
    <siteMapNode url="~/list.aspx" title="List items">
    <siteMapNode url="~/details.aspx" title="Details page" />
    <siteMapNode>
    <siteMapNode>
    <siteMap>

    Note how the details siteMapNode is nested in list ; now because of this nesting structure it will build us a nice breadcrumb trail as we keep going from home, to list and then to details as : home > List items > Details page : so this happened for us automatically.
    One problem remains however. Note how the url for the siteMapNodedetails page is static. It does not include the querystring. Thequerystring is defined at runtime dynamically, so in order to fix this,lets subscribe to the SiteMapResolve event of our sitemap as suggestedby the documentation on msdn. We will be doing this in details.aspx asin the example that follows below :
    C#
    
                  
    protected void Page_Load(object sender, EventArgs e)
    {
    SiteMap.SiteMapResolve +=
    new SiteMapResolveEventHandler(SiteMap_SiteMapResolve);
    }

    private SiteMapNode SiteMap_SiteMapResolve(Object sender,
    SiteMapResolveEventArgs e)
    {
    SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
    string currentRequest = e.Context.Request.Url.PathAndQuery;
    if (currentNode.ParentNode != null)
    currentNode.ParentNode.Url = currentRequest;

    // now return the currentNode after we modified the parentNode
    // supply it the new url which includes the querystring value.
    return currentNode;
    }
    Some things to take note here is, we are cloning the currentNode, the reason to do this is because by default we have a readonly in memory copy. Cloning the node while passing true to the clone argument allows us to clone all parent and ancestor nodes of the current node. A deep clone like this is essential because it allows us to walk down parents/children in the currentnode. For eg, in our example code above, what we want to do is modify the url of the parent page of the current details page where the code is executing. In this way we can modify the url to include the querystring we wanted.

    Another thing you want to be careful about when using SiteMapResolve method is that by default it uses aggressive caching, and so, some changes wont be visible unless there has been a file change in your application or someone touched web.config ; so during development, when you make some changes to your code in SiteMapResolve event and the changes are not being picked up, you might want to touch web.config which should recycle the appdomain and clear the cache.

     
    re: SiteMapPath Control and dynamic url based on querystring.
    by
    Gravatar

    Is there a way to display a title from the database too? im getting products to detail.aspx page and would like to have:

    Home: Category: Product Name

    Also, how could i work in sitemap with mulitple node?

    example:
    <siteMapNode url="Naboji" title="Naboji " >
      <siteMapNode url="Naboj-Detail.aspx" title="New State" />
    </siteMapNode>

    <siteMapNode url="Naboji-1.aspx" title="Naboji za puške"  description="Naboji ">
      <siteMapNode url="Naboj-Detail.aspx" title="New State1"/>
    </siteMapNode>

    As you can see i have two with same name...I know i can add Naboj-Detail.aspx# but then my sitemap is not showing my link.





    re: SiteMapPath Control and dynamic url based on querystring.
    by

    Is there a way to display a title from the database too? im getting products to detail.aspx page and would like to have:

    Home: Category: Product Name

    Also, how could i work in sitemap with mulitple node?

    example:
    <siteMapNode url="Naboji" title="Naboji " >
      <siteMapNode url="Naboj-Detail.aspx" title="New State" />
    </siteMapNode>

    <siteMapNode url="Naboji-1.aspx" title="Naboji za puške"  description="Naboji ">
      <siteMapNode url="Naboj-Detail.aspx" title="New State1"/>
    </siteMapNode>

    As you can see i have two with same name...I know i can add Naboj-Detail.aspx# but then my sitemap is not showing my link.





    re: SiteMapPath Control and dynamic url based on querystring.
    by
    I have the same problem as Kim is facing. Is there already a solution?

    re: SiteMapPath Control and dynamic url based on querystring.
    by
    Gravatar
    just fine

    re: SiteMapPath Control and dynamic url based on querystring.
    by
    Gravatar
    just fine

    12
    A penny for your thoughts