1

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);
        }
    } 
}
elbillaf
  • 1,952
  • 10
  • 37
  • 73

1 Answers1

1

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. :)

Reg Edit
  • 6,719
  • 1
  • 35
  • 46
  • I did this. The debugger says that SiteMapPath1 and Provider do not exist in the current context. There is a SiteMapPath, but it doesn't seem to have what I'm looking for. – elbillaf Jun 26 '14 at 20:37
  • What navigation are you using in conjunction with your SiteMap? For example, does your page contain a `SiteMapPath` control called SiteMapPath1? (If not, what happens when you add one?) – Reg Edit Jun 26 '14 at 20:45
  • I searched the project. There is no object named SiteMapPath or SiteMapPath1 in the entire project (so I don't understand how the debugger could see a value for SiteMapPath unless the system builds it on its own). Should I infer from your comment that I SHOULD be creating such an object? I'm rereading the source page ... doesn't say anything about it...maybe he's assuming the reader already knows this. – elbillaf Jun 26 '14 at 20:58
  • Also, if I have to include this on the page, do I have to do that on every single page or can I invoke it from Application_Start in Global.asax.cs? (Sorry if I'm getting side-tracked...just trying to think my way through how this thing is supposed to work.) – elbillaf Jun 26 '14 at 21:01
  • The ASP.NET SiteMap is generally used in conjuncton with one or other of the [Site navigation controls](http://msdn.microsoft.com/en-us/library/vstudio/e468hxky(v=vs.100).aspx#SiteNavigationControls). I was imagining you might have one on your page already, or might want to add one experimentally. In answer to your other question, no, you don't need to add a navigation control to every page, you can put it in a master page, as mentioned at the page I just linked to. – Reg Edit Jun 26 '14 at 21:10
  • Thanks, I'll read this tonight and see what I can figure out in the morning. Thanks again. – elbillaf Jun 26 '14 at 21:19
  • If you remember the comment to your previous question I explicitly mentioned that you showed the SiteMapDataSoruce, and the navigation controls (menu, tree, path) that you're using. If you don't have any of these, take for granted that your provider will never be invoked (as Reg Edit has commented). If you want to get completely sure that your code is executed, temporarily add this: `System.Diagnostics.Debugger.Break();` which will open the debugger as if you had a breakpoint on that line. I use it when I have something hart to debug. – JotaBe Jun 26 '14 at 22:48
  • I have a SiteMapDataSource. It is declared as part of a menu. I'll add those into my OP. – elbillaf Jun 27 '14 at 15:43
  • Curious. The website now seems to invoke what I wanted to invoke, namely the Initialize() and _SiteMapResolve() routines. I think I can at least debug the thing now. Thanks. I'm not sure what I did. I must have changed something without realizing. – elbillaf Jun 27 '14 at 15:55
  • I'm at least able to debug now. However, I notice that the sitemap I see in the debugger does not correspond to the sitemap file. The sitemap is being displayed correctly by the menu control. But the ExtendedSiteMapProvider class, while it is being invoked, does not get the proper sitemap data. My extended provider gets a first node of "/default.aspx" which no siblings and no children, and a parent of "~/". This through me off b/c until I noticed the first node should be "~/default.aspx" Provider is set I think correctly in web.config. – elbillaf Jun 30 '14 at 15:10
  • Suggest you post a new question for that, and include your `Web.sitemap` file. – Reg Edit Jul 02 '14 at 06:37