SiteMap导航和查询字符串

时间:2010-06-24 20:49:34

标签: c# asp.net dynamic sitemap

目前我正在尝试弄清楚如何将动态查询字符串参数添加到我的站点地图导航菜单中。例如,用户选择他想要使用的源和版本。我有一个简单的站点地图,可以创建导航链接,但用户选择的参数需要在查询字符串中传递。默认地图如下所示:

<siteMapNode url="" title=""  description="" >
   <siteMapNode url="~/Image.aspx?location=Our Products" title="Our Products" description="Our Products" />
   <siteMapNode url="~/Headline.aspx?location=Our Authors" title="Our Authors"  description="Our Authors" />
</siteMapNode>

现在,链接需要根据用户选择的内容动态添加参数。例如:

<siteMapNode url="~/Image.aspx?location=Our Products&Source=12345&Edition=asdfff" title="Our Products"  description="Our Products" />
<siteMapNode url="~/Headline.aspx?location=Our Authors&Source=12345&Edition=asdfff" title="Our Authors"  description="Our Authors" />

希望这是相当清楚的。如果有人需要更深入的解释,请告诉我。

由于

3 个答案:

答案 0 :(得分:10)

不幸的是,默认情况下不支持此功能。但是,您可以在SiteMap.SiteMapResolve中实施Global.asax事件以捕获此类扩展网址,并使用正确的网址调用SiteMapProvider.FindSiteMapNode

private void Application_Start(object sender, EventArgs e)
{
    SiteMap.SiteMapResolve += ResolveCustomNodes;
}

private SiteMapNode ResolveCustomNodes(object sender, SiteMapResolveEventArgs e)
{
    // catch ~/Image.aspx and ~/Headline.aspx
    if (e.Context.Request.AppRelativeCurrentExecutionFilePath.Equals(
        "~/Image.aspx", StringComparison.OrdinalIgnoreCase)
      || e.Context.Request.AppRelativeCurrentExecutionFilePath.Equals(
        "~/Headline.aspx", StringComparison.OrdinalIgnoreCase))
    {
        string location = context.Request.QueryString["location"];
        if (location != null) // ignore everything except location=
            return e.Provider.FindSiteMapNode(
                e.Context.Request.AppRelativeCurrentExecutionFilePath
                "?location=" + HttpUtility.UrlEncode(location));
    }
    return null; // use default implementation;
}

无需自定义SiteMapProvider,这适用于任何提供商。

现在,如果你想变得更有活力,你可以做几件事,例如(有可能的方法):

标记所有<siteMapNode>标记,其中部分查询字符串与特殊属性匹配,并通过迭代整个站点地图加载此列表。这种方法的问题在于,对于某些站点地图提供商而言,这可能是非常低效的(基于文件的提供商是与这种方法很好匹配的提供商的示例)。那你要做的就是说

<siteMapNode url="~/Image.aspx?location=Our Products"
             queryStringField="location"
             title="Our Products" description="Our Products" />

在代码中,您可以通过从根节点开始递归地找到这样的节点,并记住具有{{​​1}}属性的所有节点:

queryStringField

有了这个清单,有些人挥手,你应该能够做同样的伎俩。请注意,您可能需要缓存此列表,因为private IEnumerable<SiteMapNode> FindNodesWithQueryString(SiteMapNode node) { if (node["queryStringField"] != null) yield return node; foreach (SiteMapNode childNode in node.ChildNodes) { foreach (SiteMapNode matchingNode in FindNodesWithQueryString(childNode)) { yield return matchingNode; } } } 事件可以比您预期的更频繁地调用。特别是对于数据库类型SiteMapResolve s。

SiteMapProvider

答案 1 :(得分:0)

ASP.NET中的默认SiteMap提供程序不允许使用查询字符串。

这是很多人遇到的问题 - 编写自己的提供程序很容易,但具有查询字符串功能。

以下提供商已经为我好几年了。

http://www.csharper.net/blog/custom_sitemapprovider_incorporates_querystring_reliance.aspx

答案 2 :(得分:0)

我遇到了与使用base64,url编码的字符串作为站点地图中的查询参数相关的类似问题。最简单的解决方案是只处理MenuItemDataBound事件并在那里进行编码:

    string[] url = e.Item.NavigateUrl.Split('?');

    if (url.Length == 2)
    {
        url[1] = WebUtils.encodeString(url[1]);
    }

    e.Item.NavigateUrl = string.Join("?", url);

我的webutils方法:

    public static string encodeString(string value)
{
    return HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(value)));
}

public static string decodeString(string value)
{
    return Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.UrlDecode(value)));
}