当前位置:  开发笔记 > 编程语言 > 正文

ASP.NET MVC中的动态站点地图

如何解决《ASP.NETMVC中的动态站点地图》经验,为你挑选了4个好方法。

我正在尝试创建一个自动站点地图ActionResult,它输出一个有效的sitemap.xml文件.实际生成的文件不是问题,但我似乎无法弄清楚如何填充系统中的URL列表.这是我到目前为止的代码:

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

例如,假设我有两个控制器,每个控制器有两个与之关联的操作:

HelpController

编辑

创建

AboutController

公司

管理

我似乎无法弄清楚如何获取URL的列表:

HTTP://本地主机/帮助/编辑

HTTP://本地主机/帮助/创建

HTTP://本地主机/约/公司

HTTP://本地主机/约/管理

eduncan911.. 13

我在do-it-yourself下面发布了一个答案.但是这里有一个开箱即用的MVC站点包:

http://mvcsitemap.codeplex.com/(< - 旧网站,但有大量文档!)

https://github.com/maartenba/MvcSiteMapProvider/wiki (< - 迁移到新网站,缺少一些文档,而不是活动)

请注意,它做了很多事情:

自动地将自身注册在MVC路线搜索引擎优化/sitemap.xml响应请求(即使是/sitemap.xml没有物理文件).这与我找到的所有搜索引擎机器人完全兼容,并且当它达到10,000等时滚动.

附带一组部分视图,用于内置BreadCrumb导航!我们使用它非常广泛,虽然动态数据部分有点麻烦,但确实有效.

附带一组部分视图,可以控制Menu.

尊重Controllers和Action方法的[Authorize]安全位.

以上所有要点均由您编辑和配置的单个mvc.sitemap XML文件控制.我现在在许多项目中使用它来做上述两点或三点.让它可以在一个地方配置,并动态生成,非常好.

虽然我发现创建动态数据提供程序的能力有点麻烦(并且严重违反了您希望做的任何类型的IoC),但是一旦绕过缓存并使用自己的缓存,它确实可以完成工作并且可以很好地扩展.



1> eduncan911..:

我在do-it-yourself下面发布了一个答案.但是这里有一个开箱即用的MVC站点包:

http://mvcsitemap.codeplex.com/(< - 旧网站,但有大量文档!)

https://github.com/maartenba/MvcSiteMapProvider/wiki (< - 迁移到新网站,缺少一些文档,而不是活动)

请注意,它做了很多事情:

自动地将自身注册在MVC路线搜索引擎优化/sitemap.xml响应请求(即使是/sitemap.xml没有物理文件).这与我找到的所有搜索引擎机器人完全兼容,并且当它达到10,000等时滚动.

附带一组部分视图,用于内置BreadCrumb导航!我们使用它非常广泛,虽然动态数据部分有点麻烦,但确实有效.

附带一组部分视图,可以控制Menu.

尊重Controllers和Action方法的[Authorize]安全位.

以上所有要点均由您编辑和配置的单个mvc.sitemap XML文件控制.我现在在许多项目中使用它来做上述两点或三点.让它可以在一个地方配置,并动态生成,非常好.

虽然我发现创建动态数据提供程序的能力有点麻烦(并且严重违反了您希望做的任何类型的IoC),但是一旦绕过缓存并使用自己的缓存,它确实可以完成工作并且可以很好地扩展.


这是一个ASP.NET站点地图,而不是搜索引擎的sitemap.xml文件

2> eduncan911..:

如同提及的那样,您希望反映您的模型命名空间并获取实现IController的所有类.获得集合后,您需要反思以查看成员(方法)返回ActionResult类型的内容.

也许您可以创建自己的属性[SitemapAttribute],它允许您有选择地指定要在站点地图中索引的方法(即Index(),而不是Edit()).是的,我喜欢控制哪些方法(url)被编写的想法.

这是一个很好的问题,因为我只是想做同样的事情.+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.
  }
}

关于如何进行反射,这里有一篇很好的MSDN文章,可以让你了解反思:

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

好问题!



3> dp...:

我看了一下Maarten Balliauw的方法,但是对于我正在尝试做的事情似乎有些过分.

我已经将一个临时解决方案整合在一起.我只是传递控制器和动作名称来生成URL.为了生成URL,我使用以下代码:

    List urlList = new List();
    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" }));

其中GetUrl如下:

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

这似乎是现在的诀窍,不过我确实喜欢将actionfilter应用于某些自动拉到一起的动作.



4> Ian Mercer..:

定义ActionFilterAttribute这样的内容以放置任何Action方法,该方法是您要在站点地图中列出的实际页面: -

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

现在将这样的内容添加到您的全局应用程序启动代码中,或者在sitemap.xml中使用它生成代码: -

   // 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().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
            }
        }
    }

您可以将属性类扩展为可能还包括更新提示的频率.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有