2009-04-07 49 views
28

Tôi đang cố gắng tạo một sơ đồ trang web ActionResult tự động xuất ra một tệp sitemap.xml hợp lệ. Thế hệ thực sự của tập tin không phải là một vấn đề, nhưng tôi dường như không thể tìm ra cách để đưa vào danh sách các URL trong hệ thống. Dưới đây là đoạn code tôi có cho đến nay:Sơ đồ trang web động trong ASP.NET MVC

public ContentResult Sitemap() 
    { 
     XNamespace xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9"; 
     XElement root = new XElement(xmlns + "urlset"); 

     //some kind of foreach here to get the loc variable for all URLs in the site 
     //for each URL in the collection, add it to the root element as here 

     //root.Add(
     // new XElement("url", 
     //  new XElement("loc", "http://google.com"), 
     //  new XElement("changefreq", "daily"))); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (StreamWriter writer = new StreamWriter(ms, Encoding.UTF8)) 
      { 
       root.Save(writer); 
      } 

      return Content(Encoding.UTF8.GetString(ms.ToArray()), "text/xml", Encoding.UTF8); 
     } 
    } 

Ví dụ, giả sử tôi có hai bộ điều khiển, và mỗi bộ điều khiển có hai hành động liên kết với chúng:

HelpController

  • Sửa
  • Tạo

AboutController Công ty

  • Quản lý

tôi dường như không thể tìm ra cách để có được một danh sách như của URL:

+1

Gần đây, giống như câu trả lời từ @ eduncan911, giải pháp tốt nhất là sử dụng http://mvcsitemap.codeplex.com/ dự án đang hoạt động và cập nhật, hỗ trợ cắt an ninh và sẽ tạo sitemap.xml. Nó cũng có thể tự động nén sơ đồ trang web nếu tác nhân hỗ trợ cho nó và phân tách sơ đồ trang web thành các sơ đồ trang web phụ nếu trang web quá lớn vì tiêu chuẩn sitemap.xml chỉ có giới hạn đối với các nút 50k. – CallMeLaNN

+0

Cảm ơn CallMeLaNN. Gần đây tôi đã cập nhật câu trả lời để liệt kê các điểm đó và hơn thế nữa, cũng như liệt kê trang web mà nó đã chuyển đến. – eduncan911

Trả lời

6

Tôi đã xem xét cách tiếp cận của Maarten Balliauw theo nhận xét của likwid, nhưng có vẻ như quá mức cho những gì tôi đang cố gắng làm.

Tôi đã cùng nhau tấn công một giải pháp tạm thời. Tôi chỉ đơn giản là truyền tên bộ điều khiển và hành động để tạo URL. Để tạo ra các URL, tôi đang sử dụng đoạn mã sau:

List<string> urlList = new List<string>(); 
    urlList.Add(GetUrl(new { controller = "Help", action = "Edit" })); 
    urlList.Add(GetUrl(new { controller = "Help", action = "Create" })); 
    urlList.Add(GetUrl(new { controller = "About", action = "Company" })); 
    urlList.Add(GetUrl(new { controller = "About", action = "Management" })); 

nơi getURL như sau:

protected string GetUrl(object routeValues) 
    { 
     RouteValueDictionary values = new RouteValueDictionary(routeValues); 
     RequestContext context = new RequestContext(HttpContext, RouteData); 

     string url = RouteTable.Routes.GetVirtualPath(context, values).VirtualPath; 

     return new Uri(Request.Url, url).AbsoluteUri; 
    } 

Điều này dường như làm các trick cho bây giờ, mặc dù tôi làm như ý tưởng của việc áp dụng actionfilter cho các hành động nhất định được tự động kéo lại.

0

Các bạn đã thử một cái gì đó như thế này:

http://blog.maartenballiauw.be/post/2008/08/29/Building-an-ASPNET-MVC-sitemap-provider-with-security-trimming.aspx

Sau khi đọc câu hỏi của bạn, tôi thấy rằng bạn muốn một cái gì đó một chút khác biệt so với các ví dụ tôi cung cấp. Tôi nghĩ bạn sẽ phải phản ánh tất cả các bộ điều khiển đã biết và hành động của họ để xây dựng một sơ đồ trang web động.

Sẽ đơn giản hơn nếu sử dụng cơ sở dữ liệu hoặc tệp sơ đồ trang web làm nguồn của bạn.

7

Như đề cập đến likwid, bạn muốn phản ánh theo không gian tên của mô hình và có được tất cả các lớp triển khai IController. Một khi bạn có bộ sưu tập, bạn muốn phản ánh để xem những gì Thành viên (phương pháp) trả về kiểu ActionResult.

Có lẽ bạn có thể tạo thuộc tính của riêng bạn, [SitemapAttribute] cho phép bạn chỉ định chọn phương pháp lập chỉ mục trong sơ đồ trang web (ví dụ: Chỉ mục(), chứ không phải Chỉnh sửa()). Vâng, tôi thích ý tưởng kiểm soát những phương thức (url) nào được viết.

Đây là một câu hỏi tuyệt vời vì tôi chỉ đang nghĩ đến việc làm tương tự. +1!

// Controller abstract implements IController 
public class HelpController : Controller 
{ 
    public HelpController() 
    { 
    } 

    [Sitemap] 
    public ActionResult Index() 
    { 
    // does get written to the file, cause of [Sitemap] 
    } 

    public ActionResult Create() 
    { 
    // does not get mapped to the file 
    } 

    public ActionResult Edit() 
    { 
    // does not get mapped to the file 
    } 

    [Sitemap] 
    public ActionResult ViewArticle() 
    { 
    // would get indexed. 
    } 
} 

Đối với cách làm việc phản ánh, đây là một bài viết MSDN tốt để giúp bạn giới thiệu để phản ánh:

http://msdn.microsoft.com/en-us/library/ms172331.aspx

Câu hỏi hay!

+0

Bạn có thể đăng một ví dụ về cách sử dụng sự phản chiếu để xây dựng nội dung không? Cụ thể cách lấy URL từ hành động? –

+0

THanks Mike, nhưng tôi không có bất kỳ mã nào. Nó đã chỉ là một sự gợi ý thôi mà. Dưới đây có vẻ là các ví dụ khác. – eduncan911

2

Vì vậy, nhận được các bộ điều khiển và hành động dường như tôi trở thành một phần tương đối nhỏ. Phần khó khăn là có thể nhận được tất cả các giá trị tham số có thể mà bạn có thể muốn hiển thị trong các url của sơ đồ trang web của bạn. Nếu bạn có mẫu URL như {controller}/{action}/{id}, thì bạn sẽ không thể xác định thông qua phản ánh ý nghĩa của id là gì hoặc các giá trị có thể có. Điều tốt nhất bạn có thể làm là xác định loại hệ thống.

Điều gì đã xảy ra với tôi khi tôi đang xem xét điều này là một sơ đồ trang web thực sự chỉ là một chế độ xem dữ liệu trang web của bạn. Vì vậy, một ý nghĩ ngẫu nhiên tôi đã có được rằng nếu bạn kế thừa từ một bộ điều khiển cơ sở trong ứng dụng của bạn, và bạn có một phương pháp trên mà điều khiển cơ sở đó phải được thực hiện, ví dụ:

abstract ActionResult SiteMapSnippet(); 

Sau đó, bạn có thể tạo ra một SiteMapController mà gọi mỗi bộ điều khiển khác trong giải pháp và yêu cầu chúng cho đoạn mã của chúng và sau đó kết hợp chúng lại với nhau trong một chế độ xem cuối cùng. Sắp xếp của một bộ điều khiển tổng hợp, mặc dù đó không phải là một khái niệm đã được thêm vào khung này.

13

Tôi đã đăng câu trả lời do-it-yourself xuống dưới đây. Nhưng đây là một gói nào đó ra khỏi hộp cho các trang web MVC:

http://mvcsitemap.codeplex.com/ (< - trang web cũ, nhưng với tài liệu phong phú!)

https://github.com/maartenba/MvcSiteMapProvider/wiki (< - chuyển đến địa điểm mới, thiếu một số tài liệu, và không phải là hoạt động)

Lưu ý rằng nó vô số điều:

  • automagically đăng ký chính nó trong các tuyến đường MVC để đáp ứng với SEO /sitemap.xm l yêu cầu (mặc dù không có tệp vật lý cho /sitemap.xml). Điều này hoàn toàn tương thích với tất cả các rô bốt công cụ tìm kiếm mà tôi đã tìm thấy, cũng như di chuyển khi đến 10.000, v.v.
  • Đi kèm với một bộ chế độ xem một phần để sử dụng cho BreadCrumb điều hướng tích hợp! Chúng tôi sử dụng điều này khá rộng rãi, mặc dù phần dữ liệu động là một chút cồng kềnh, nó hoạt động.
  • Đi kèm với một tập hợp các chế độ xem một phần cho Menu cũng được kiểm soát.
  • Tôn trọng các bit bảo mật [Ủy quyền] của các phương pháp Bộ điều khiển và Hành động của bạn.

Tất cả các điểm trên được điều khiển từ tệp XML mvc.sitemap duy nhất mà bạn chỉnh sửa và định cấu hình. Tôi đã sử dụng điều này trong một số dự án bây giờ để làm 2 hoặc 3 của các điểm trên. Có tất cả các cấu hình ở 1 nơi, và tự động tạo ra, thực sự là tốt đẹp.

Mặc dù tôi thấy khả năng tạo các nhà cung cấp dữ liệu năng động hơi phức tạp (và vi phạm nghiêm trọng bất kỳ loại IoC nào bạn muốn), nó hoàn thành công việc và cân bằng một khi bạn bỏ qua bộ nhớ đệm và sử dụng bộ nhớ riêng của mình.

+8

Đó là một sơ đồ trang web ASP.NET không phải là một tệp sitemap.xml cho một công cụ tìm kiếm –

+1

@Hightechrider nó tạo ra một sitemap.xml cho các bản đồ đã đăng ký của bạn. Kích hoạt là tầm thường. https://github.com/maartenba/MvcSiteMapProvider/wiki/Exporting-the-sitemap-for-search-engine-indexing – tugberk

+1

Đó là mới, cảm ơn bạn đã chỉ ra và vị trí mới. –

5

Xác định một ActionFilterAttribute như thế này để đưa vào bất kỳ phương pháp hành động đó là một trang thực tế mà bạn muốn liệt kê trong sitemap của bạn: -

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
public class MVCUrlAttribute : ActionFilterAttribute 
{ 
    public string Url { get; private set; } 

    public MVCUrlAttribute(string url) 
    { 
     this.Url = url; 
    } 

    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     // Put this 'canonical url' into the model (which feeds the view) 
     // to help search engines with issues of duplicate content 
     filterContext.Controller.ViewData["CanonicalUrl"] = url; 
     base.OnResultExecuting(filterContext); 
    } 
} 

Bây giờ thêm một cái gì đó như thế này để áp mã số bắt đầu toàn cầu của bạn, hoặc sử dụng nó trong mã tạo sitemap.xml của bạn: -

// Find all the MVC Routes 
    Log.Debug("*** FINDING ALL MVC ROUTES MARKED FOR INCLUSION IN SITEMAP"); 
    var allControllers = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(Controller))); 
    Log.DebugFormat("Found {0} controllers", allControllers.Count()); 

    foreach (var controllerType in allControllers) 
    { 
     var allPublicMethodsOnController = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance); 
     Log.DebugFormat("Found {0} public methods on {1}", allPublicMethodsOnController.Count(), controllerType.Name); 

     foreach (var publicMethod in allPublicMethodsOnController) 
     { 
      var mvcurlattr = publicMethod.GetCustomAttributes(true).OfType<MVCUrlAttribute>().FirstOrDefault(); 
      if (mvcurlattr != null) 
      { 
       string url = mvcurlattr.Url; 
       Log.Debug("Found " + controllerType.Name + "." + publicMethod.Name + " <-- " + url); 
       Global.SiteMapUrls.Add(url); //<-- your code here using url 
      } 
     } 
    } 

Bạn có thể mở rộng lớp thuộc tính để có thể cũng bao gồm tần suất gợi ý cập nhật.

+0

Xin chào. Sơ đồ trang web này có hợp lệ theo nguyên tắc của google không? –

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