我正在尝试创建一个自动站点地图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);
}
}
Run Code Online (Sandbox Code Playgroud)
例如,假设我有两个控制器,每个控制器有两个与之关联的操作:
HelpController
AboutController
我似乎无法弄清楚如何获取URL的列表:
edu*_*911 13
我在do-it-yourself下面发布了一个答案.但是这里有一个开箱即用的MVC站点包:
http://mvcsitemap.codeplex.com/(< - 旧网站,但有大量文档!)
https://github.com/maartenba/MvcSiteMapProvider/wiki (< - 迁移到新网站,缺少一些文档,而不是活动)
请注意,它做了很多事情:
以上所有要点均由您编辑和配置的单个mvc.sitemap XML文件控制.我现在在许多项目中使用它来做上述两点或三点.让它可以在一个地方配置,并动态生成,非常好.
虽然我发现创建动态数据提供程序的能力有点麻烦(并且严重违反了您希望做的任何类型的IoC),但是一旦绕过缓存并使用自己的缓存,它确实可以完成工作并且可以很好地扩展.
如同提及的那样,您希望反映您的模型命名空间并获取实现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.
}
}
Run Code Online (Sandbox Code Playgroud)
关于如何进行反射,这里有一篇很好的MSDN文章,可以让你了解反思:
http://msdn.microsoft.com/en-us/library/ms172331.aspx
好问题!
我看了一下Maarten Balliauw的方法,但是对于我正在尝试做的事情似乎有些过分.
我已经将一个临时解决方案整合在一起.我只是传递控制器和动作名称来生成URL.为了生成URL,我使用以下代码:
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" }));
Run Code Online (Sandbox Code Playgroud)
其中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;
}
Run Code Online (Sandbox Code Playgroud)
这似乎是现在的诀窍,不过我确实喜欢将actionfilter应用于某些自动拉到一起的动作.
定义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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在将这样的内容添加到您的全局应用程序启动代码中,或者在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<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
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将属性类扩展为可能还包括更新提示的频率.
| 归档时间: |
|
| 查看次数: |
19882 次 |
| 最近记录: |