Mapping 将Web.SiteMap与动态URL一起使用(URL路由)

Mapping 将Web.SiteMap与动态URL一起使用(URL路由),mapping,url-routing,sitemap,wildcard,sitemapnode,Mapping,Url Routing,Sitemap,Wildcard,Sitemapnode,我想在Web.SiteMap中匹配“近似”匹配 Sitemap静态站点地图提供程序运行良好,除了一件事。是静电的 因此,如果我的页面上10000篇文章中的每一篇都需要一个sitemapnode,就像这样: site.com/articles/1/article-title site.com/articles/2/other-article-title site.com/articles/3/other-article-reach site.com/articles/9999/the-last

我想在Web.SiteMap中匹配“近似”匹配

Sitemap静态站点地图提供程序运行良好,除了一件事。是静电的

因此,如果我的页面上10000篇文章中的每一篇都需要一个sitemapnode,就像这样:

  • site.com/articles/1/article-title
  • site.com/articles/2/other-article-title
  • site.com/articles/3/other-article-reach
  • site.com/articles/9999/the-last-article
是否有一些通配符映射我可以做的网站地图,以匹配任何在文章

或者在我的Webforms页面中,是否有方法手动设置当前节点

在使用ASP.NETMVC框架进行此操作时,我发现了一些“帮助”,但仍然在寻找一个很好的Webforms解决方案


我想我要做的是创建一个自定义的站点地图提供商

我想这不完全是对你问题的回答,但也许它能给你一个想法。我曾经编写过一个继承SiteMapPath的DynamicItemAppath类。我在Web.sitemap中的每个
标记中使用自定义属性,如下所示:

<siteMapNode url="dynamicpage.aspx" title="blah" params="id" />


然后DynamicItemAppath类获取“id”参数值,从数据库检索内容,并使用正确的标题和链接覆盖当前呈现的sitemap项节点。这需要做一点工作,但如果做得正确,这是提供动态页面支持的一种非常简洁的方式。

这是对上述评论的回应。我不能发布完整的代码,但我的提供者基本上就是这样工作的

假设您有一个页面article.aspx,它使用查询字符串参数“id”检索并显示文章标题和正文。然后在Web.sitemap中显示:

<siteMapNode url="/article.aspx" title="(this will be replaced)" param="id" />

然后,创建该类:

public class DynamicSiteMapPath : SiteMapPath
{
  protected override void InitializeItem(SiteMapNodeItem item)
  {
    if (item.ItemType != SiteMapNodeItemType.PathSeparator)
    {
      string url = item.SiteMapNode.Url;
      string param = item.SiteMapNode["param"];

      // get parameter value
      int id = System.Web.HttpContext.Current.Request.QueryString[param];

      // retrieve article from database using id
      <write your own code>

      // override node link
      HyperLink link = new HyperLink();
      link.NavigateUrl = url + "?" + param + "=" + id.ToString();
      link.Text = <the article title from the database>;
      link.ToolTip = <the article title from the database>;
      item.Controls.Add(link);
    }
    else
    {
      // if current node is a separator, initialize as usual
      base.InitializeItem(item);
    }
  }
}
公共类DynamicItemAppath:SiteMapPath
{
受保护的覆盖无效初始值项(SiteMapNodeItem项)
{
if(item.ItemType!=SiteMapNodeItemType.PathSeparator)
{
字符串url=item.SiteMapNode.url;
字符串param=item.SiteMapNode[“param”];
//获取参数值
int id=System.Web.HttpContext.Current.Request.QueryString[param];
//使用id从数据库检索文章
//覆盖节点链接
超级链接=新的超级链接();
link.NavigateUrl=url+“?”+param+“=”+id.ToString();
link.Text=;
link.ToolTip=;
项。控件。添加(链接);
}
其他的
{
//如果当前节点是分隔符,则按常规初始化
基础。初始化项(项目);
}
}
}
最后,在代码中使用此提供程序就像使用静态提供程序一样

<mycontrols:DynamicSiteMapPath ID="dsmpMain" runat="server" />

我的课程比这更复杂,但这些是基础。您不必使用querystring参数,只需分析您正在使用的友好url,并使用它来检索正确的内容。为了最大限度地减少每个请求的额外db查找,可以向提供程序添加缓存机制(文章标题通常不会经常更改)


希望这能有所帮助。

我一直遇到这个问题,坦率地说,没有找到任何让我高兴的解决方案。。。所以我从这里那里借用了一些想法。我的解决方案是多部分的:a)让SiteMapProvider找到处理请求的实际页面并使用其节点,b)使用标准技术从那里更新sitemapnode

A) 我一直遇到的问题是,如果没有正确的虚拟路径,SiteMap.CurrentNode将为null,并启动SiteMapResolve函数。要解决此问题,我将XmlSiteMapProvider子类化并覆盖CurrentNode:

 namespace WebFormTools
{
    class RouteBaseSitemapProvider : XmlSiteMapProvider
    {
        public override SiteMapNode CurrentNode
        {
            get
            {
                var node = base.CurrentNode;


                if (node == null) 
                {
                    // we don't have a node, see if this is from a route
                    var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;

                    if (page != null && page.RouteData != null)
                    {
                        // try and get the Virtual path associated with this route
                        var handler = page.RouteData.RouteHandler as PageRouteHandler;

                        if (handler != null) {
                            // try and find that path instead.
                            node = FindSiteMapNode(handler.VirtualPath);
                        }
                    }

                }

                return node;
            }
        }
    }
}
基本上,如果默认实现找不到任何内容,请查找路由(如果有),并尝试使用处理程序的虚拟路径查找节点

此处是my Web.Config、Global.asax和SiteMap文件的一部分,仅供参考:

添加提供程序

    <siteMap defaultProvider="RouteBaseSitemapProvider">
  <providers>
    <add name="RouteBaseSitemapProvider" type="WebFormTools.RouteBaseSitemapProvider" siteMapFile="Web.sitemap" />
  </providers>
</siteMap>
和网站地图:

        <siteMapNode url="~/Evals/New.aspx" title="New Eval - {type}"  description="" />

B) I子类System.Web.UI.Page,恰当地命名为BaseClass,它添加了一个方法来注册SiteMapResolve事件的处理程序:

public System.Web.SiteMapNode Process(System.Web.SiteMapNode currentNode)
    {
        if (currentNode == null) return currentNode;

        var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;

        if (page != null && page.RouteData != null)
        {

            Dictionary<Regex, string> replacements = new Dictionary<Regex, string>();

            // build a list of RegEx to aid in converstion, using RegEx so I can ignore class.  Technically I could also
            foreach (var key in page.RouteData.Values.Keys)
            {
                replacements.Add(new Regex(string.Format("\\{{{0}\\}}", key), RegexOptions.IgnoreCase), page.RouteData.Values[key].ToString());              
            }


            // navigate up the nodes
            var activeNode = currentNode;
            while (activeNode != null)
            {
                // to the replacements
                foreach(var replacement in replacements)
                {
                    activeNode.Title =  replacement.Key.Replace(activeNode.Title, replacement.Value);
                }

                activeNode = activeNode.ParentNode;
            }

        }

        return currentNode;
    }
public System.Web.SiteMapNode进程(System.Web.SiteMapNode当前节点)
{
如果(currentNode==null)返回currentNode;
var page=HttpContext.Current.CurrentHandler作为System.Web.UI.page;
if(page!=null&&page.RouteData!=null)
{
字典替换=新字典();
//建立一个正则表达式列表来帮助对话,使用正则表达式这样我就可以忽略类。从技术上来说,我也可以
foreach(page.RouteData.Values.Keys中的var键)
{
Add(newregex(string.Format(\\{{{0}\\}),key),RegexOptions.IgnoreCase),page.RouteData.Values[key].ToString();
}
//向上导航节点
var-activeNode=currentNode;
while(activeNode!=null)
{
//给替代者
foreach(替换中的var替换)
{
activeNode.Title=replacement.Key.Replace(activeNode.Title,replacement.Value);
}
activeNode=activeNode.ParentNode;
}
}
返回当前节点;
}

我仍然需要适当地映射URL(将使用接收路由的页面的URL),这是SAN路由信息。我可能会在站点地图中使用一个自定义属性来告诉节点如何呈现URL。

我想知道更多关于这方面的信息。听起来很有趣,酷!谢谢我也将发布一个我提出的解决方案。我如何在我的aspx页面中使用这个类?需要帮忙吗
public System.Web.SiteMapNode Process(System.Web.SiteMapNode currentNode)
    {
        if (currentNode == null) return currentNode;

        var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;

        if (page != null && page.RouteData != null)
        {

            Dictionary<Regex, string> replacements = new Dictionary<Regex, string>();

            // build a list of RegEx to aid in converstion, using RegEx so I can ignore class.  Technically I could also
            foreach (var key in page.RouteData.Values.Keys)
            {
                replacements.Add(new Regex(string.Format("\\{{{0}\\}}", key), RegexOptions.IgnoreCase), page.RouteData.Values[key].ToString());              
            }


            // navigate up the nodes
            var activeNode = currentNode;
            while (activeNode != null)
            {
                // to the replacements
                foreach(var replacement in replacements)
                {
                    activeNode.Title =  replacement.Key.Replace(activeNode.Title, replacement.Value);
                }

                activeNode = activeNode.ParentNode;
            }

        }

        return currentNode;
    }