.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 });
        }
posted @ 2013-08-16 18:11  yusufeng  阅读(1068)  评论(4编辑  收藏  举报