.net mvc下的Areas和小写Url
首先是一个站点有前台后台两部分,这个要怎么来做。可以在mvc项目中添加区域(Areas)来实现,当添加一个名为Admin的区域时,项目下多了一个Areas/Admin目录,里边有Controllers、Models、Views这个我人个觉得目录太深维护操作不便。关于前台和后台的模块分离可以参考园子里的<<使用Areas分离ASP.NET MVC项目>> http://kb.cnblogs.com/page/144561/这篇文章。
然后就是Url小写的问题,后台的Url一般没什么要求,前台那部分一般都是要求要小写的,Controller和Action正常都是首字母大,然后生成出来的Url那部分也是大写的,一个个的在路由里定义不太现实,调用生成Url时小写Controller和Action看起来也很奇怪的,像Url.Action(“Details”,"Product”)写成Url.Action(“details”,"product”)。园子里也有一篇ASP.NET MVC:自定义Route生成小写Url,因为分离了项目,映射路由有些问题,要使用带NameSpace参数的MapRoute。用.NET Reflector看了一下 RouteCollectionExtensions 里的对应方法源码,它的实现方式如下:
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } Route route2 = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; Route item = route2; if ((namespaces != null) && (namespaces.Length > 0)) { item.DataTokens["Namespaces"] = namespaces; } routes.Add(name, item); return item; }
自定义路由的代码
public class LowerCaseUrlRoute : Route { /// <summary> /// 需要小写的键值 /// </summary> private static readonly string[] RequiredKeys = new[] { "controller", "action" }; #region 实现继承类的构造 public LowerCaseUrlRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { } public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler) { } public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler) { } public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler) { } #endregion /// <summary> /// 重写GetVirtualPath以生成小写Url /// </summary> /// <param name="requestContext"></param> /// <param name="values"></param> /// <returns></returns> public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { LowerRouteValues(requestContext.RouteData.Values); LowerRouteValues(values); LowerRouteValues(Defaults); return base.GetVirtualPath(requestContext, values); } /// <summary> /// 转换要小写的键值 /// </summary> /// <param name="values"></param> private void LowerRouteValues(RouteValueDictionary values) { foreach (var key in RequiredKeys) { var value = values[key]; values[key] = value.ToString().ToLower(); } } } public static class LowerCaseUrlRouteExtensions { /// <summary> /// LowerCaseUrlRouter的扩展方法 /// </summary> /// <param name="routes"></param> /// <param name="name"></param> /// <param name="url"></param> /// <param name="defaults"></param> /// <returns></returns> public static LowerCaseUrlRoute MapUrl(this RouteCollection routes, string name, string url, object defaults) { var route = new LowerCaseUrlRoute(url, new RouteValueDictionary(defaults), new RouteValueDictionary(), //constraints new RouteValueDictionary(), //dataTokens new MvcRouteHandler()); //获取当前项目控制器的Namespace,使其默认应用在这个Namespace下 var type = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType; if (type != null) { var namespaces = new[] { type.Namespace + ".Controllers" }; route.DataTokens["Namespaces"] = namespaces; } routes.Add(name, route); return route; } public static LowerCaseUrlRoute MapUrl(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) { var route = new LowerCaseUrlRoute(url, new RouteValueDictionary(defaults), new RouteValueDictionary(), //constraints new RouteValueDictionary(), //dataTokens new MvcRouteHandler()); if ((namespaces != null) && (namespaces.Length > 0)) { route.DataTokens["Namespaces"] = namespaces; } routes.Add(name, route); return route; } }
在Global.asax中的使用如下:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapUrl("home", "", new { controller = "Home", action = "Index" }); routes.MapUrl("index", "{controller}.html", new { controller = "Villa", action = "Index" }); routes.MapUrl("details", "{controller}/{id}.html", new { controller = "Villa", action = "details" }); routes.MapUrl("default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }); }