2008-11-15 83 views
9

我想匹配「近似」在web.sitemap中使用web.sitemap中動態網址(URL路由)

匹配的web.sitemap中的靜態站點地圖提供者效果很好,除了一兩件事。它是靜態的!

所以,如果我將不得不爲每個10000篇的的SiteMapNode我的網頁上像這樣:

  • site.com/articles/1/article-title
  • site.com/文章/ 2 /另一-文章標題
  • site.com/articles/3/another-article-again
  • ...
  • site.com/articles/9999/the-last-article

是否有某種通配符映射,我可以用SiteMap進行匹配以匹配文章下的所有內容?

或者在我的Webforms頁面中,是否有辦法手動設置當前節點?

在使用ASP.Net MVC框架進行此操作時,我發現this page上存在一些「幫助」,但仍然在爲Webforms尋找一個好的解決方案。

我想我將要做的是創建一個自定義地圖提供商

回答

7

這是對上述評論的迴應。我無法發佈完整的代碼,但這基本上是我的提供者的工作原理。

假設您有一個頁面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); 
    } 
    } 
} 

最後,您使用此提供在你的代碼,就像你使用靜態提供商。

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

我的課是比這更復雜,但這些都是基礎知識。而不是使用查詢字符串參數,您可以分析您使用的友好網址,然後使用它來檢索正確的內容。爲了最大限度地減少每個請求的額外數據庫查找,可以向提供者添加一個緩存機制(文章標題通常不會經常更改)。

希望這會有所幫助。

+0

酷!謝謝。我將發佈一個我也提出的解決方案。 – Armstrongest 2008-11-27 23:54:15

2

這並不完全回答你的問題,我認爲,但也許它給你的想法。我曾經寫過一個繼承SiteMapPath的DynamicSiteMapPath類。我用一個自定義屬性在Web.sitemap中的每個<siteMapNode>標籤,就像這樣:

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

然後DynamicSiteMapPath類獲取「ID」參數值,從數據庫中獲取內容,並覆蓋當前呈現站點地圖項目具有正確標題和鏈接的節點。這需要一些工作,但是如果正確完成,這是一種提供動態頁面支持的非常好的方式。

+0

我想知道更多關於此的信息。聽起來很有趣。 – Armstrongest 2008-11-20 03:24:29

2

我一直在遇到這個問題,坦率地說,沒有找到任何讓我快樂的解決方案......所以我借鑑了來自這裏和那裏的想法。我的解決方案是多方面的: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; 
      } 
     } 
    } 
} 

基本上,如果默認的實現沒有發現什麼,查找路線(如果有的話),並試圖找到使用處理程序的虛擬路徑節點。

僅供參考這裏是我的web.config,Global.asax中和Sitemap文件的一部分:

添加提供商

<siteMap defaultProvider="RouteBaseSitemapProvider"> 
    <providers> 
    <add name="RouteBaseSitemapProvider" type="WebFormTools.RouteBaseSitemapProvider" siteMapFile="Web.sitemap" /> 
    </providers> 
</siteMap> 

路線:

  routes.MapPageRoute("EvalRoutes", 
      "Evals/{type}/New.aspx", 
      "~/Evals/New.aspx"); 

而且網站地圖:

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

B)我子類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; 
    } 

我仍然需要有URL映射適當地(在將使用接收路由的頁面的URL),這是無路由信息。我可能會在站點地圖中使用自定義屬性來告訴節點如何呈現URL。