创建测试工程

分别在vs2013和vs2015中创建mvc项目,并创建First、Second、Three三个Area,每个Area下面创建一个HomeController和Index视图。修改RouteConfig.cs中的路由注册方法,添加命名空间

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

       public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },                namespaces: new[] { "RouteDebuggerMvc5Demo.Controllers" }
            );
        }

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

修改三个Area的路由注册方法,添加命名空间:

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

  public class FirstAreaRegistration : AreaRegistration 
    {        public override string AreaName 
        {            get 
            {                return "First";
            }
        }        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(                "First_default",                "First/{controller}/{action}/{id}",                new { action = "Index", id = UrlParameter.Optional },                namespaces: new[] { "RouteDebuggerMvc5Demo.Areas.First.Controllers" }
            );
        }
    }

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

使用nuget添加RouteDebugger引用,在Web.config中配置启用 <add key="RouteDebugger:Enabled" value="true" />,运行起来:

VS2013中升序

Matches Current RequestUrlDefaultsConstraintsDataTokens
FalseFirst/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerMvc5Demo.Areas.First.Controllers, area = First, UseNamespaceFallback = False
FalseSecond/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerMvc5Demo.Areas.Second.Controllers, area = Second, UseNamespaceFallback = False
FalseThree/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerMvc5Demo.Areas.Three.Controllers, area = Three, UseNamespaceFallback = False
False{resource}.axd/{*pathInfo}(null)(empty)(null)
True{controller}/{action}/{id}controller = Home, action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerMvc5Demo.Controllers
True{*catchall}(null)(null)(null)

VS2015中降序

All Routes
Matches Current RequestUrlDefaultsConstraintsDataTokens
FalseThree/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerDemo.Areas.Three.Controllers, RouteDebuggerDemo, area = Three, UseNamespaceFallback = False
FalseSecond/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerDemo.Areas.Second.Controllers, RouteDebuggerDemo, area = Second, UseNamespaceFallback = False
FalseFirst/{controller}/{action}/{id}action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerDemo.Areas.First.Controllers, RouteDebuggerDemo, area = First, UseNamespaceFallback = False
False{resource}.axd/{*pathInfo}(null)(empty)(null)
True{controller}/{action}/{id}controller = Home, action = Index, id = UrlParameter.Optional(empty)Namespaces = RouteDebuggerDemo.Controllers, RouteDebuggerDemo
True{*catchall}(null)(null)(null)

如果在VS2013中的某个路由注册有问题,一直没有显现出来,升级到VS2015后出现了404就有可能是路由匹配顺序导致的。问题参考:Why did the order of Areas in RegisterAllAreas change with Visual Studio 2015?

手动修改路由顺序

默认在 *.csproj文件中的路由顺序是

<Compile Include="Areas\First\Controllers\HomeController.cs" />
<Compile Include="Areas\First\FirstAreaRegistration.cs" />
<Compile Include="Areas\Second\Controllers\HomeController.cs" />
<Compile Include="Areas\Second\SecondAreaRegistration.cs" />
<Compile Include="Areas\Three\Controllers\HomeController.cs" />
<Compile Include="Areas\Three\ThreeAreaRegistration.cs" />

修改成

<Compile Include="Areas\First\Controllers\HomeController.cs" />
<Compile Include="Areas\First\FirstAreaRegistration.cs" /> 
<Compile Include="Areas\Three\Controllers\HomeController.cs" />
<Compile Include="Areas\Three\ThreeAreaRegistration.cs" />
<Compile Include="Areas\Second\Controllers\HomeController.cs" />
<Compile Include="Areas\Second\SecondAreaRegistration.cs" />

重新访问页面查看路由,顺序已经改变了(对比上面VS2015里的顺序),可以通过这种方法把最常用的路由调到最前面,提高匹配速度。经测试添加新的Area后,调整的路由顺序不会变回去,可以放心使用。

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

参考链接:.Net MVC Area Registration Sequence

 

RouteDebugger 简介

作者地址:ASP.NET Routing Debugger,代码结构图如下:

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

程序集属性[assembly: PreApplicationStartMethod(typeof(PreApplicationStart), "Start")] 使PreApplicationStart的Start方法在Application_Start方法之前执行,

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

public static void Start()
        {            bool flag = Convert.ToBoolean(ConfigurationManager.AppSettings["RouteDebugger:Enabled"]);            if (flag)
            {
                DynamicModuleUtility.RegisterModule(typeof(RouteDebuggerHttpModule));
            }
        }

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

最后处理请求的是DebugHttpHandler里的ProcessRequest方法把匹配的路由信息获取出来,代码如下:

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训

  //处理请求
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest request = context.Request;            if (!this.IsRoutedRequest(request) || context.Response.ContentType == null || !context.Response.ContentType.Equals("text/html", StringComparison.OrdinalIgnoreCase))
            {                return;
            }            string text = string.Empty;
            RequestContext requestContext = request.RequestContext;            if (request.QueryString.Count > 0)
            {
                RouteValueDictionary routeValueDictionary = new RouteValueDictionary();                foreach (string text2 in request.QueryString.Keys)
                {                    if (text2 != null)
                    {
                        routeValueDictionary.Add(text2, request.QueryString[text2]);
                    }
                }
                VirtualPathData virtualPath = RouteTable.Routes.GetVirtualPath(requestContext, routeValueDictionary);                if (virtualPath != null)
                {
                    text = "<p><label style=\"font-weight: bold; font-size: 1.1em;\">Generated URL</label>: ";
                    text = text + "<strong style=\"color: #00a;\">" + virtualPath.VirtualPath + "</strong>";
                    Route route = virtualPath.Route as Route;                    if (route != null)
                    {
                        text = text + " using the route \"" + route.Url + "\"</p>";
                    }
                }
            }            string text3 = string.Empty;
            RouteData routeData = requestContext.RouteData;
            RouteValueDictionary values = routeData.Values;
            RouteBase route2 = routeData.Route;            string text4 = string.Empty;            using (RouteTable.Routes.GetReadLock())
            {                foreach (RouteBase current in RouteTable.Routes)
                {                    //查询请求与路由是否匹配
                    bool flag = current.GetRouteData(requestContext.HttpContext) != null;                    
                    string isMatchRequest = string.Format("<span{0}>{1}</span>", DebugHttpHandler.BoolStyle(flag), flag);                    string url = "n/a";                    string defaults = "n/a";                    string constraints = "n/a";                    string dataTokens = "n/a";
                    Route route3 = this.CastRoute(current);                    if (route3 != null)
                    {
                        url = route3.Url;
                        defaults = DebugHttpHandler.FormatDictionary(route3.Defaults);
                        constraints = DebugHttpHandler.FormatDictionary(route3.Constraints);
                        dataTokens = DebugHttpHandler.FormatDictionary(route3.DataTokens);
                    }
             
                 text4 += string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>", new object[]
                    {
                        isMatchRequest,
                        url,
                        defaults,
                        constraints,
                        dataTokens
                    });
                }
            }            string text10 = "n/a";            string text11 = "";            if (!(route2 is DebugRoute))
            {                foreach (string current2 in values.Keys)
                {
                    text3 += string.Format("\t<tr><td>{0}</td><td>{1}&nbsp;</td></tr>", current2, values[current2]);
                }                foreach (string current3 in routeData.DataTokens.Keys)
                {
                    text11 += string.Format("\t<tr><td>{0}</td><td>{1}&nbsp;</td></tr>", current3, routeData.DataTokens[current3]);
                }
                Route route4 = route2 as Route;                if (route4 != null)
                {
                    text10 = route4.Url;
                }
            }            else
            {
                text10 = string.Format("<strong{0}>NO MATCH!</strong>", DebugHttpHandler.BoolStyle(false));
            }
            text3 = "text3";
            text10 = "text10";
            text4 = "text4";
            text11 = "text11";
            text = "text";

移动开发培训,Android培训,安卓培训,手机开发培训,手机维修培训,手机软件培训


网友评论