2008-11-15 37 views
9

Tôi muốn để phù hợp với "gần đúng" phù hợp trong Web.SiteMapSử dụng Web.SiteMap với Dynamic URL (URL Routing)

Các Web.Sitemap cung cấp sitemap tĩnh hoạt động tốt, ngoại trừ một điều. TÌNH TRẠNG CỦA IT!

Vì vậy, nếu tôi sẽ phải có một sitemapnode cho mỗi 10.000 bài viết trên trang của mình như sau:

  • site.com/articles/1/article-title
  • site.com/ bài viết/2/khác-article-tiêu đề
  • site.com/articles/3/another-article-again
  • ...
  • site.com/articles/9999/the-last-article

Có một số loại ánh xạ Wildcard tôi có thể thực hiện với Sơ đồ trang web để khớp với Bất kỳ điều gì trong Bài viết không?

Hoặc có thể trong Trang biểu mẫu web của tôi, có cách nào để Đặt thủ công nút hiện tại không?

Tôi đã tìm thấy trợ giúp "bit" trên this page khi thực hiện việc này với ASP.Net MVC Framework, nhưng vẫn đang tìm kiếm giải pháp tốt cho Webforms.

Tôi nghĩ rằng những gì tôi sẽ phải làm là tạo ra một nhà cung cấp tùy chỉnh SiteMap

Trả lời

7

Điều này là để trả lời nhận xét ở trên. Tôi không thể đăng mã đầy đủ, nhưng đây là cơ bản cách nhà cung cấp của tôi hoạt động.

Giả sử bạn có một trang article.aspx và nó sử dụng tham số chuỗi truy vấn "id" để truy xuất và hiển thị tiêu đề bài viết và nội dung. Thì đây là trong Web.sitemap:

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

Sau đó, bạn tạo lớp này:

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); 
    } 
    } 
} 

Cuối cùng, bạn sử dụng nhà cung cấp này trong mã của bạn giống như bạn sẽ sử dụng các nhà cung cấp tĩnh.

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

Lớp của tôi phức tạp hơn thế này, nhưng đây là những điều cơ bản. Thay vì sử dụng tham số chuỗi truy vấn, bạn chỉ có thể phân tích url thân thiện bạn đang sử dụng và sử dụng thay vào đó để truy xuất nội dung chính xác. Để giảm thiểu các tra cứu db bổ sung với mọi yêu cầu, bạn có thể thêm một cơ chế lưu vào bộ nhớ đệm cho nhà cung cấp (tiêu đề bài viết thường sẽ không thay đổi thường xuyên).

Hy vọng điều này sẽ hữu ích.

+0

Tuyệt! Cảm ơn. Tôi sẽ đăng một giải pháp mà tôi đã đưa ra quá. – Armstrongest

+0

Tôi làm cách nào để sử dụng lớp này trong trang aspx của mình? xin vui lòng giúp đỡ –

2

Đây không phải là hoàn toàn một câu trả lời cho câu hỏi của bạn tôi nghĩ, nhưng có lẽ nó mang lại cho bạn một ý tưởng. Tôi đã từng viết một lớp DynamicSiteMapPath kế thừa SiteMapPath. Tôi sử dụng một thuộc tính tùy chỉnh trong mỗi <siteMapNode> thẻ trong Web.sitemap, như thế này:

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

Sau đó, lớp DynamicSiteMapPath nhận được "id" tham số giá trị, lấy nội dung từ cơ sở dữ liệu, và ghi đè các mục sitemap hiện render nút có tiêu đề và liên kết chính xác. Nó sẽ mất một chút công việc, nhưng khi thực hiện một cách chính xác đây là một cách rất gọn gàng để cung cấp hỗ trợ trang động.

+0

Tôi rất muốn biết thêm thông tin về điều này. Nghe thú vị. – Armstrongest

2

Tôi đã gặp phải vấn đề này và thẳng thắn, không tìm ra giải pháp nào làm tôi hạnh phúc ... vì vậy tôi mượn ý tưởng từ đây và ở đó. Giải pháp của tôi là đa phần: a) có SiteMapProvider tìm trang thực sự xử lý yêu cầu và sử dụng nút của nó và b) sử dụng các kỹ thuật tiêu chuẩn để cập nhật sitemapnode từ đó.

A) Sự cố mà tôi tiếp tục gặp phải là nếu tôi không có đường dẫn ảo chính xác, SiteMap.CurrentNode sẽ là rỗng và kích hoạt hàm SiteMapResolve. Để giải quyết việc này tôi subclassed XmlSiteMapProvider và overrode 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; 
      } 
     } 
    } 
} 

Về cơ bản nếu việc thực hiện mặc định không tìm thấy bất cứ điều gì, nhìn lên con đường (nếu có) và cố gắng tìm các nút sử dụng đường dẫn ảo của handler.

Để tham khảo ở đây là một phần của Web.Config của tôi, Global.asax và SiteMap file:

Thêm nhà cung cấp

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

Tuyến:

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

Và SiteMap:

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

B) Tôi phân lớp System.Web.UI.Page, hòn đảo có tên BaseClass, có thêm một phương pháp để đăng ký xử lý cho sự kiện 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; 
    } 

tôi vẫn cần phải có bản đồ các URL một cách thích hợp (sẽ sử dụng URL của trang nhận được tuyến đường), đây là thông tin định tuyến không đúng. Tôi có thể sẽ sử dụng thuộc tính tùy chỉnh trong sơ đồ trang web để cho nút biết cách hiển thị URL.

Các vấn đề liên quan