Search code examples
asp.netsitemapquerystringparametersitemapprovider

Query string paramaters for a sitemap


I'm using VWD 2010, ASP.Net, C#. I have a sitemap that works, BUT I need to be able to link to external sites and send parameters. I found some code that looks like it should work, but I'm missing some kind of understanding or they seem to be assuming I know something I don't. (The other fellow seems to have understood it perfectly.)

REVISED: Adding to show how menu and sitedatasource are declared.

            <asp:SiteMapDataSource runat="server" ID="siteMapDataSource" ShowStartingNode="false" />

            <asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" DataSourceID="siteMapDataSource"
                EnableViewState="False" IncludeStyleBlock="False" Orientation="Horizontal" 
                BackColor="#F7F6F3" DynamicHorizontalOffset="2" Font-Names="Verdana" 
                Font-Size="0.8em" ForeColor="#7C6F57" StaticSubMenuIndent="10px">
                <DynamicHoverStyle BackColor="#7C6F57" ForeColor="White" />
                <DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
                <DynamicMenuStyle BackColor="#F7F6F3" />
                <DynamicSelectedStyle BackColor="#5D7B9D" />
                <DynamicItemTemplate>
                    <%# Eval("Text") %>
                </DynamicItemTemplate>
                <StaticHoverStyle BackColor="#7C6F57" ForeColor="White" />
                <StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
                <StaticSelectedStyle BackColor="#5D7B9D" />
            </asp:Menu>

Note that the menu works to the extent that it correctly displays the data in Web.sitemap.

Here's the link to the original code: http://weblogs.asp.net/jgaylord/adding-querystring-parameters-to-the-sitemapnode

My sitemap works, but it doesn't seem to be invoking this extended sitemapprovider. I'm sure this provider doesn't do what I need...at this point I'm just trying to make sure it's getting invoked. So, I set some breaks in the code in Initialize() and in the the SmartSiteMapProvider_SiteMapResolve() routine. I'm just trying to get it to invoke when I think it should invoke at this point. I can't modify it if I can't debug it, and I can't debug it, if I can't get it invoked.

I'm using the C# code for that and have duplicated it below. I have put it in it's own class file at the top level called ExtendedSiteMapProvider.cs

Here's the section from the web.config I'm using.

<siteMap enabled="true" defaultProvider="ExtendedSiteMapProvider">
  <providers>
    <clear/>
    <add name="ExtendedSiteMapProvider" type="Configuration.ExtendedSiteMapProvider" siteMapFile="web.sitemap" securityTrimmingEnabled="true" />
  </providers>
</siteMap>

The C# code from that site.

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web;

using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.SessionState;

namespace Configuration
{
    public class ExtendedSiteMapProvider : XmlSiteMapProvider
    {
        public override void Initialize(string name, NameValueCollection attributes)
        {
            base.Initialize(name, attributes);

            this.SiteMapResolve += SmartSiteMapProvider_SiteMapResolve;
        }

        static SiteMapNode SmartSiteMapProvider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)
        {
            if ((SiteMap.CurrentNode == null)) return null;
            SiteMapNode temp = SiteMap.CurrentNode.Clone(true);
            SiteMapNode tempNode = temp;


            while (tempNode != null)
            {
                string qs = GetQueryString(tempNode, e.Context);

                if (qs != null)
                {
                    tempNode.Url += qs;
                }

                tempNode = tempNode.ParentNode;
            }

            return temp;
        }

        private static string GetQueryString(SiteMapNode node, HttpContext context)
        {
            if (node["queryStringToInclude"] == null) return null;

            NameValueCollection values = new NameValueCollection();

            string[] vars = node["queryStringToInclude"].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 static string NameValueCollectionToString(NameValueCollection col)
        {
            string[] parts = new string[col.Count];
            string[] keys = col.AllKeys;

            for (int i = 0; i <= keys.Length - 1; i++)
            {
                parts[i] = keys[i] + "=" + col[keys[i]];
            }

            return "?" + string.Join("&", parts);
        }
    } 
}

Solution

  • It looks as though it should work. Set a breakpoint in Page_Load, and when you hit it, have a look at your navigation control properties. For instance, enter SiteMapPath1 in the Immediate window. The Provider property will be either XmlSiteMapProvider, or, if it's working, ExtendedSiteMapProvider.

    If the breakpoint in Page_Load is not hit either, then that is your answer--you're somehow not running it in debug mode. :)