Dynamic sitemap in ASP.NET MVC

前端 未结 7 633
小蘑菇
小蘑菇 2021-01-30 09:04

I\'m trying to create an automatic sitemap ActionResult that outputs a valid sitemap.xml file. The actual generation of the file is not a problem, but I can\'t seem to figure o

相关标签:
7条回答
  • 2021-01-30 09:41

    I posted a do-it-yourself answer down below. But here is a package that does it out of the box for MVC sites:

    http://mvcsitemap.codeplex.com/ (<- old site, but with extensive documentation!)

    https://github.com/maartenba/MvcSiteMapProvider/wiki (<- moved to new site, lacking some documentation, and not as active)

    Note that it does a multitude of things:

    • Automagically registers itself in the Mvc routes to respond to SEO /sitemap.xml requests (even though there is no physical file for /sitemap.xml). This is completely compatible with all search engine robots I've found, as well as rolling over when it gets to 10,000, etc.
    • Comes with a set of partial views to use for BreadCrumb navigation built-in! We use this quite extensively, though the dynamic data portion is a bit cumbersome, it does work.
    • Comes with a set of partial views for Menu to be controlled as well.
    • Honors the [Authorize] security bits of your Controllers and Action methods.

    All of the above points are controlled from the single mvc.sitemap XML file you edit and configure. I've used this in a number of projects now to do 2 or 3 of the above points. Have it all configurable in 1 place, and dynamically generated, is really nice.

    Though I find the ability to create dynamic data providers a bit cumbersome (and grossly violates any type of IoC you wish to do), it does get the job done and scales nicely once you bypass their caching and use your own.

    0 讨论(0)
  • 2021-01-30 09:41

    As likwid mentions, you want to reflect upon your model(s) namespace and obtain all classes that implement IController. Once you have the collection, you want to reflect to see what Members (methods) return the type ActionResult.

    Perhaps you can create your own attribute, [SitemapAttribute] that lets you selectively specify what methods to index in the sitemap (i.e., Index(), but not Edit()). Yeah, I like that idea of controlling which methods (urls) gets written.

    This is an excellent question because I was just thinking of doing the same. +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.
      }
    }
    

    For how to do reflection, here's a good MSDN article to get you introduced to reflection:

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

    Good question!

    0 讨论(0)
  • 2021-01-30 09:45

    Have you tried something like this:

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

    After re-reading your question, I see that you want something a little different than the example I provided. I think you would have to reflect all of the known controllers and their actions to build a sitemap dynamically.

    It would be far simpler to use a database or sitemap file as your source I think.

    0 讨论(0)
  • 2021-01-30 09:58

    I took a look at Maarten Balliauw's approach per likwid's comment, but it seems to be overkill for what I'm trying to do.

    I've hacked together a temporary solution. I'm simply passing the controller and action names to generate the URL's. In order to generate the URL's, I'm using the following code:

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

    where GetUrl is as below:

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

    This seems to do the trick for now, though I do like the idea of having actionfilter's applied to certain actions that get pulled together automatically.

    0 讨论(0)
  • 2021-01-30 09:58

    So, the getting of the controllers and actions seems to me to be the relatively trivial part. The hard part is being able to get all the possible parameter values that you might want to show in the urls of your sitemap. If you have a URL pattern like {controller}/{action}/{id}, then you're not going to be able to determine through reflection what the meaning of id is, or the possible values. The best you can do is determine the system type.

    What occurred to me as I was looking at this is that a sitemap is really just another view of your site's data. So one random thought I had was that if you inherit from a base controller in your app, and you have a method on that base controller that has to be implemented, e.g.:

    abstract ActionResult SiteMapSnippet();
    

    Then you could create a SiteMapController which calls each of the other controllers in the solution and asks them for their snippet, and then renders them all together in one final view. Sort of a composite controller, though that's not a concept that's been added to this framework yet.

    0 讨论(0)
  • 2021-01-30 10:03

    Take a look at the code behind Phil Haack's "Route Debugger":

    http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

    0 讨论(0)
提交回复
热议问题