博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VS2013和VS2015中MVC 区域路由匹配顺序相反
阅读量:5068 次
发布时间:2019-06-12

本文共 10550 字,大约阅读时间需要 35 分钟。

创建测试工程

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

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" }            );        }

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

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" }            );        }    }

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

VS2013中升序

Matches Current Request Url Defaults Constraints DataTokens
False First/{controller}/{action}/{id} action = Index, id = UrlParameter.Optional (empty) Namespaces = RouteDebuggerMvc5Demo.Areas.First.Controllers, area = First, UseNamespaceFallback = False
False Second/{controller}/{action}/{id} action = Index, id = UrlParameter.Optional (empty) Namespaces = RouteDebuggerMvc5Demo.Areas.Second.Controllers, area = Second, UseNamespaceFallback = False
False Three/{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 Request Url Defaults Constraints DataTokens
False Three/{controller}/{action}/{id} action = Index, id = UrlParameter.Optional (empty) Namespaces = RouteDebuggerDemo.Areas.Three.Controllers, RouteDebuggerDemo, area = Three, UseNamespaceFallback = False
False Second/{controller}/{action}/{id} action = Index, id = UrlParameter.Optional (empty) Namespaces = RouteDebuggerDemo.Areas.Second.Controllers, RouteDebuggerDemo, area = Second, UseNamespaceFallback = False
False First/{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就有可能是路由匹配顺序导致的。问题参考:

手动修改路由顺序

默认在 *.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后,调整的路由顺序不会变回去,可以放心使用。

参考链接:

 

RouteDebugger 简介

作者地址:,代码结构图如下:

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

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

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

//处理请求        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 = "

: "; text = text + "" + virtualPath.VirtualPath + ""; Route route = virtualPath.Route as Route; if (route != null) { text = text + " using the route \"" + route.Url + "\"

"; } } } 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("
{1}", 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("{0}{1}{2}{3}{4}", 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{0}{1} ", current2, values[current2]); } foreach (string current3 in routeData.DataTokens.Keys) { text11 += string.Format("\t{0}{1} ", current3, routeData.DataTokens[current3]); } Route route4 = route2 as Route; if (route4 != null) { text10 = route4.Url; } } else { text10 = string.Format("
NO MATCH!", DebugHttpHandler.BoolStyle(false)); } text3 = "text3"; text10 = "text10"; text4 = "text4"; text11 = "text11"; text = "text"; context.Response.Write(string.Format("\r\n
\r\n
\r\n

\r\n

Route Debugger

\r\n
\r\n

\r\n Type in a url in the address bar to see which defined routes match it. \r\n A {

{*catchall}} route is added to the list of routes automatically in \r\n case none of your routes match.\r\n

\r\n

\r\n To generate URLs using routing, supply route values via the query string. example: http://localhost:14230/?id=123\r\n

\r\n

: {1}

\r\n {5}\r\n
\r\n
\r\n
\r\n
\r\n {0}\r\n
Route Data
Key Value
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n {4}\r\n
Data Tokens
Key Value
\r\n
\r\n

\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n {2}\r\n
All Routes
Matches Current Request Url Defaults Constraints DataTokens
\r\n

\r\n

Current Request Info

\r\n

\r\n AppRelativeCurrentExecutionFilePath is the portion of the request that Routing acts on.\r\n

\r\n

AppRelativeCurrentExecutionFilePath: {3}

\r\n
\r\n
", new object[] { text3, text10, text4, request.AppRelativeCurrentExecutionFilePath, text11, text })); }

注:RouteDebugger的源码是通过ILSpy反编译的。

结束语

 抽出时间去验证路由顺序是因为两个错误引起的:

1.升级vs2013的mvc4解决方案到vs2015后所有的Area路由失效,返回404错误。以为是vs2015对mvc4的支持不够(刚出来是对mvc4是有点问题),就撤销升级返回vs2013了。

2.在vs2013中添加了一个新的Area,排在了以前的所有路由之后,出现404错误。通过RouteDebugger发现是路由的顺序问题,所以想到上面那个问题应该也是顺序问题,不应该是vs2015的缺陷。

 

希望这篇文章可以帮助你避免遇到同样的问题,觉着有用就推荐一下吧

 

转载于:https://www.cnblogs.com/zeroes/p/vs2015-arearoute-orderbyname-desc.html

你可能感兴趣的文章
C# BS消息推送 SignalR介绍(一)
查看>>
WPF星空效果
查看>>
WPF Layout 系统概述——Arrange
查看>>
PIGOSS
查看>>
几款Http小服务器
查看>>
openSuse beginner
查看>>
Codeforces 620E(线段树+dfs序+状态压缩)
查看>>
css3动画属性
查看>>
Mongodb 基本命令
查看>>
控制文件的备份与恢复
查看>>
软件目录结构规范
查看>>
mysqladmin
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
设置虚拟机虚拟机中fedora上网配置-bridge连接方式(图解)
查看>>
[置顶] Android仿人人客户端(v5.7.1)——人人授权访问界面
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android实现 ScrollView + ListView无滚动条滚动
查看>>
java学习笔记之String类
查看>>
UVA 11082 Matrix Decompressing 矩阵解压(最大流,经典)
查看>>
硬件笔记之Thinkpad T470P更换2K屏幕
查看>>