在mvc中,Url地址是利用routing特性来支持,但是这个Routing有个问题,多个不同的地址和指向同一个action方法,
例如:
http://test.com (默认) http://test.com/ (斜杠结尾) http://test.com/Home (带有Controller) http://test.com/Home/Action (带有Controller和Action) http://test.com/home/Action (不同的情况)
解决方法:通过使用注册全局的filter
先定义一个filter
public class RemoveDuplicateContentAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var routes = RouteTable.Routes; var requestContext = filterContext.RequestContext; var routeData = requestContext.RouteData; var dataTokens = routeData.DataTokens; if (dataTokens["area"] == null) dataTokens.Add("area", ""); var vpd = routes.GetVirtualPathForArea(requestContext, routeData.Values); if (vpd != null) { var virtualPath = vpd.VirtualPath.ToLower(); var request = requestContext.HttpContext.Request; if (virtualPath != request.Path) { filterContext.Result = new RedirectResult(virtualPath + request.Url.Query, true); } } base.OnActionExecuting(filterContext); } }
然后注册这个filter:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //整个程序所有控制器都使用HandlerError来处理错误 //不过它只处理500系列错误,404类型需要单独处理 filters.Add(new HandleErrorAttribute()); filters.Add(new RemoveDuplicateContentAttribute()); }
总结:
首先获取当前的RequestContext和RouteData,然后判断如果当前没有使用Area的话就为DataToken添加一个空值,这个非常重要,否则,后面再使用Area特性的话就会出错
接着该filter通过RouteData获取虚拟path,然后toLower转成小写
然后和当前request的path进行比较,如果不一致就重定向到小写的虚拟path上,这样搜索引擎就能识别当多个请求其实都是对应虚拟的path的真实地址上,也就是唯一的action地址,
对于SEO:确保一个地址对应一个内容是非常重要的,