ASP.NET MVC Route详解
在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor。在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎。Razor在减少代码冗余、增强代码可读性和Visual Studio智能感知方面,都有着突出的优势。Razor一经推出就深受广大ASP.Net开发者的喜爱。Routing深入详解
首先,ASP.Net MVC项目是URL请求驱动的,为什么访问localhost/home/index会传递给HomeController中名为index的action(即HomeController类中的index方法)?
下面,我们一一来看下。
1.1 Routing的作用
假如有一个请求:localhost/home/index,那么路由需要做的事情如下:
(1)确定Controller
(2)确定Action
(3)确定其他参数
(4)根据识别出来的数据,将请求传递给Controller和Action
1.2 神奇的路由规则
根据路由的作用,我们可以知道它是一个“指路人”,指示我们的请求应该到达哪个Controller中的Action。那么,它是根据什么规则来指路的呢?我们可以在App_Start文件夹中的RouteConfig类中找到这个神奇的规则是如何制定的。

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

(1)首先,第一句routes.IgnoreRoute代表对所有axd的资源访问请求进行忽略,直接进行URL访问;这里可以阅读参考资料第(5)篇,了解其详细含义,这里就不再赘述;
(2)然后,第二句开始使用MapRoute方法对整个网站定义了一个路由识别规则,这个规则的name是Default,url规则为:{controller}/{action}/{id}。例如我们要访问的URL为:localhost/home/index,在这个URL中,localhost是域名, 所以首先要去掉域名部分: home/index,也是就对应了上面代码中的这种URL结构: {controller}/{action}/{id}。正是因为我们建立了这种URL结构的识别规则,,所以能够识别出 Controller是home, action是index, id没有则为默认值""。
(3)在MapRoute方法中为所有URL请求定义了一个defaults默认值:controller为空则指向Home,action为空则指向Index,而id则是可选的,非必须要的。
这里,对于路由规则需要注意的有两点:
(1)可以有多条路由规则;
(2)路由规则是有顺序的(前面的规则被匹配后,后面的规则就不再匹配);
我们可以在RegisterRoutes这个方法中添加一条自定义路由规则,并取名为Default2,具体规则代码如下:
routes.MapRoute(
name: "Default2",
url: "{controller}-{action}-{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
这下如果我们以:localhost/Home-Index来访问时,我们原本想要的是根据Default2这个路由规则访问Home控制器下的Index这个Action,但却被告知以404提示:

这是为什么呢?我们再来看看RegisterRoutes这个方法:

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 }
); routes.MapRoute(
name: "Default2",
url: "{controller}-{action}-{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

我们刚刚提到,路由规则是有顺序的(前面的规则被匹配后,后面的规则就不再匹配)。那么,可以推断,由于Default2在Default之后,有可能我们的请求localhost/Home-Index已经被Default这个规则所匹配了,因此Default2规则根本没有出场Show一下。那么,在Default规则中,它将Home-Index作为Controller的名字匹配,去访问Home-Index这个Controller,而Action使用默认的Index,那么它所请求的应该是这个URL:/localhost/Home-Index/Index。由于网站中,并没有Home-Index这个Controller,所以也就出现了刚刚那个404页面。
1.3 MapRoute方法介绍
(1)MapRoute方法提供了以下几种方式的重载:
MapRoute( string name, string url);MapRoute( string name, string url, object defaults);MapRoute( string name, string url, string[] namespaces);MapRoute( string name, string url, object defaults, object constraints); MapRoute( string name, string url, object defaults, string[] namespaces);MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);
我们在上面所使用的便是第二种重载。
(2)MapRoute方法参数详细介绍:
①name参数:
规则名称, 可以随意起名。不可以重名,否则会发生错误: “路由集合中已经存在名为“Default”的路由。路由名必须是唯一的”。
②url参数:
url获取数据的规则,这里不是正则表达式,将要识别的参数括起来即可,比如: {controller}/{action}
最少只需要传递name和url参数就可以建立一条Routing(路由)规则,比如实例中的规则完全可以改为:
routes.MapRoute( "Default", "{controller}/{action}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

routes.MapRoute(
name: "Default2",
url: "{controller}-{action}-{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { controller = @"\d{4}" }
);

例如:通过第IRouteConstraint 接口可以限制请求的类型(是GET还是POST)。因为System.Web.Routing中提供了HttpMethodConstraint类,,这个类实现了IRouteConstraint 接口。

我们可以通过为RouteValueDictionary字典对象添加键为"httpMethod", 值为一个HttpMethodConstraint对象来为路由规则添加HTTP 谓词的限制,比如限制一条路由规则只能处理GET请求:httpMethod = new HttpMethodConstraint( "GET" )

routes.MapRoute(
name: "Default2",
url: "{controller}-{action}-{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new {
controller = @"\d{4}",
httpMethod = new HttpMethodConstraint("GET") }
);

1.4 URL路由实例详解
一般来说,对于一个网站为了SEO友好,网址的URL层次最好不要超过三层:localhost/{频道}/{具体网页},其中域名第一层, 频道第二层, 那么最后的网页就只剩下最后一层了。如果使用默认实例中的“{controller}/{action}/{其他参数}"的形式则会影响网站的SEO。
假设我们有一个综合型服务网站,其中有租房频道、酒店频道、KTV频道、电影院频道等等。我们应该怎样来设计URL路由规则呢?
(1)首先,我们知道:可以有多条路由规则,但是路由规则是有顺序的(前面的规则被匹配后,后面的规则就不再匹配);所以,我们可以定义多条路由规则,粒度细的模块(比如:具体的酒店列表页面)路由规则放最前面,粒度粗的模块(比如:门户网站的首页)路由规则放在最后面。
(2)其次,根据模块粒度划分层次结构,以粒度粗细排序为:网站首页->频道首页->具体内容;
(3)最后,我们可以看一个具体的URL路由实例来分析一下:

// 酒店列表页匹配
routes.MapRoute(
"酒店列表页",
"hotels/{action}-{city}-{price}-{star}",
new { controller = "Hotel", action = "list", city = "beijing", price = "-1,-1", star = "-1" },
new { city = @"[a-zA-Z]*", price = @"(\d)+\,(\d)+", star = "[-1-5]" }
); // 酒店频道所有匹配
routes.MapRoute(
"酒店首页",
"hotels/{*iiii}",
new { controller = "Hotel", action = "default", hotelid = "" }
); // 网站首页默认匹配
routes.MapRoute(
"网站首页",
"{*values}",
new { controller = "Home", action = "index" }
);

(4)我们可以分析一下上面的路由规则所实现的功能:
①访问 www.mywebsite.com/hotels/list-chengdu-100,200-3 会访问酒店频道的列表页,并传入查询参数(price为100,200,star为3);
②访问 www.mywebsite.com/hotels 下面的任何其他页面地址,都会跳转到酒店首页;
③访问 www.mywebsite.com 下面的任何地址,如果未匹配上面2条,则跳转到首页;
(5)根据上面的规则和实现的功能,我们可以做一个简单的总结如下:
①Routing规则有顺序(按照添加是的顺序),如果一个url匹配了多个路由规则,则按照第一个匹配的路由规则执行。
②由于上面的规则,要将具体频道的具体页面放在最上方,将频道首页 和 网站首页 放在最下方。
③{*values}表示后面可以使用任意的格式。
1.5 URL路由调试
在ASP.Net MVC中,默认是不允许对路由规则进行调试的。但是,我们可以通过使用RouteDebug来辅助进行调试。
(1)首先,我们下载RouteDebug.dll,MvcContrib.dll到我们的项目中,并添加对其的引用。
(2)其次,在Global.asax中的Application_Start方法中添加一句代码:
RouteDeug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
RouteDeug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}

(3)最后,F5调试运行,我们请求localhost/Home-Index这个URL时,可以清楚地发现,系统将Home-Index匹配了第一条默认路由规则,也就是将Home-Index作为Controller的名称进行匹配,这也就证明了为什么我们输入这个请求不会匹配第二条Default2的路由规则出现刚刚那个404页面了。



ASP.NET MVC Route详解的更多相关文章
- Asp.Net Mvc 控制器详解
理解控制器 控制器的角色 (1)中转作用:控制器通过前面的学习大家应该知道它是一个承上启下的作用,根据用户输入,执行响应行为(动 作方法),同时在行为中调用模型的业务逻辑,返回给用户结果(视图). ( ...
- asp.net MVC ViewData详解
转自:http://www.cnblogs.com/gaopin/archive/2012/11/13/2767515.html 控制器向视图中传值ViewData详解 1.将一个字符串传值到视图中 ...
- asp.net Mvc 路由详解,非常详细.
关于路由的理解 为什么要定义路由?路由的定义在开发中的工作量非常小,但是非常重要,因为任何请求都离不开路由. 各个电商网站的 URL 使用非常灵活,都离不开路由的定义,请大家参考几家电商的 URL 如 ...
- ASP.NET MVC 过滤器详解
http://www.fwqtg.net/asp-net-mvc-%E8%BF%87%E6%BB%A4%E5%99%A8%E8%AF%A6%E8%A7%A3.html 我经历了过滤器的苦难,我想到了还 ...
- ASP.NET 运行时详解 揭开请求过程神秘面纱
对于ASP.NET开发,排在前五的话题离不开请求生命周期.像什么Cache.身份认证.Role管理.Routing映射,微软到底在请求过程中干了哪些隐秘的事,现在是时候揭晓了.抛开乌云见晴天,接下来就 ...
- ASP.NET生命周期详解
最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...
- ASP.NET生命周期详解 [转]
最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...
- ASP.NET生命周期详解(转)
看到好文章需要分享. 最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多 ...
- MVC过滤器详解
MVC过滤器详解 APS.NET MVC中(以下简称"MVC")的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理. ...
随机推荐
- 第二个hibernate Annotation版本的helloworld
经过第一次的 hibernate 我发现每一个数据库表都对应了一个类,并且每一个类都要新建一个文件进行配置 很麻烦! 于是便出现了Annotation版本的hibernate. 具体如下: 1.同 ...
- 性能调优必备利器之 JMH
if 快还是 switch 快?HashMap 的初始化 size 要不要指定,指定之后性能可以提高多少?各种序列化方法哪个耗时更短? 无论出自何种原因需要进行性能评估,量化指标总是必要的. 在大部分 ...
- BrainF**k的编译器
按照语法编写了这个"编译器"(对于解释性语言而言"编译"二字的确很奇怪). 功能: 1."编译".运行一个后缀为 '.bf' ...
- [CF453D]Little Pony and Elements of Harmony
题目 点这里看题目. 分析 设\(count(x)\)为\(x\)的二进制中\(1\)的个数.因此\(f(u,v)=count(u\oplus v)\) 看一看每次转移,我们发现最不友好的 ...
- git添加所有新文件
git add -A 提交所有变化 git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new) git add . 提交新文件(new)和被修改(mod ...
- 看到这些常见的android面试题,你慌了吗?
最近参加了一些Android工程师岗位的面试,总结了一些常见的考点,希望能帮到正在面试的你(答案还在整理中)! 1.Java调用函数传入实际参数时,是值传递还是引用传递? 2.单例模式的DCL方式,为 ...
- mysql面试题总结
Mysql中的myisam与innodb的区别? InnoDB存储引擎的四大特性? 什么是事务? 数据库事务的四大特性? 不考虑事务的隔离性,会发生几种问题? MySQL数据库提供的四种隔离级别? 有 ...
- ca77a_c++__一个打开并检查文件输入的程序_流对象_操作文件
/*ca77a_c++__一个打开并检查文件输入的程序 习题:8.13 8.14*/ /*ca77a_c++__一个打开并检查文件输入的程序 习题:8.13 8.14 */ #include < ...
- 机器学习——打开集成方法的大门,手把手带你实现AdaBoost模型
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第25篇文章,我们一起来聊聊AdaBoost. 我们目前为止已经学过了好几个模型,光决策树的生成算法就有三种.但是我们每 ...
- Refresh Java
当你的知识来源于实践, 你可能会忽略很多细节. 当你的知识来源于阅读, 你可能会很快的忘掉. 那么, 不如在空闲之余, 浏览一遍, 把觉得有必要的记录下来, 也便于以后温故而知新, 何乐而不为呢? 于 ...