网址路由(Routing)在ASP.NET MVC中有两个主要用途,一个用途是匹配通过浏览器传来的HTTP请求,另一个用途则是将适当的网址返回浏览器。
首先我们来看下第一个用途,也就是匹配通过浏览器传来的HTTP请求。
客户端对ASP.NET网站发出请求时,能够通过Routing找到合适的HttpHandler来处理网页,大致的处理流程为:
图一 客户端对ASP.NET 网站发出请求的流程
如果HttpHandler是由MvcHandler来处理的,那么,此时就会进入ASP.NET MVC的执行生命周期,并且会找到适当的Controller与Action来对其进行处理,并将信息反馈到客户端。
其次是将适当的网址返回浏览器。
网址路由的另一个用途是决定ASP.NET MVC应该输出什么样的网址并将其返回给浏览器,一般来说,跳转地址或者在View中显示超链接时,都需要参考网址路由的定义,因为这样才能动态决定ASP.NET MVC输出的网址应该是什么。我们接下来看个例子,假如首先默认网址路由。
Public static void RegisterRoutes(RouteCollection routes) {routes.IgnoreRoute(“{resource}.axd/{*pathInfo} ”);routes.MapRoute( “Default”,“{controller}/{action}/{id}”,new {controller =”home”,action =”Index”,id =UrlParameter.Optional } );} protected void Application_Start() {AreaRegistration.RegisterAllAreas();RegisterRoutes(RouteTable.Routes); } |
在这里我们定义了如下两个默认的网址路由:
- IgnoreRoute
设定*.axd等格式的网址路径不通过ASP.NET MVC执行。例如,ASP.NET内置的Trace.axd文件或其他默认的HttpHandler对象都不通过ASP.NET MVC进行处理。
- MapRoute
MapRoute()方法是定义ASP.NET MVC网址路由最主要的方式,每一个路由都定义了以下3个参数:
- 路由名称。
- 对网址路径如何对应到控制器、动作与路由值的设定。
- 控制器、动作和其他路由值的默认值。
通过这个默认的MapRoute()方法可以得知,在浏览器的地址栏输入“http://localhost/Home/About”时,通过Routing的对应,由于网址路径的一部分为“Home/About”,所以会对应出“{controller}”为“Home”,“{action}”为“About”。因此,ASP.NET MVC会先进入“Controllers”目录,找到Home控制器(也就是HomeController.cs文件),然后再找到这个控制器内的About公开方法啊(Public Method)。这个公开方法就是MVC的Action,也就是实际执行网页主要程序的入口。
当我们在浏览器的地址栏中输入“http://localhost”来访问网站首页时,通过Routing的对应,由于网址路径部分没有任何内容,所以会使用MapRoute()方法的第三个参数所设定的默认值来代替。因此,会先进入“Controllers”目录,找到Home控制器,然后再找到Index公开方法,并进一步执行ASP.NET MVC的所有过程。
由于我们默认定义了两个网址路由,按照ASP.NET Routing的规则,当HTTP提出请求后,URL会进行网址路由的对比,而且是由上而下地一条一条匹配,直到符合HTTP请求的网址为止。
1、例如:http://localhost/Trace.axd/a/b/c/d/e
匹配的顺序:
(1) 匹配 routes.IgnoreRoute命名空间的“{resource}.axd/{*pathInfo} ”网址格式。
(2) {resource}.axd匹配到“Trace.axd”,因此继续匹配下一个RouteValue表达式。
(3) 匹配“{*pathInfo}”,得到“a/b/c/d/e”。
(4) 因为所有的RouteValue表达式都匹配成功,所有该HTTP请求会由此网址路由提供服务。
匹配结果:
该网址使用routes.IgnoreRoute命名空间进行处理,也就是说,ASP.NET MVC为忽略此请求,改以ASP.NET 架构本身继续处理。
2、例如:http://localhost/Member/Detail?id=123
匹配的顺序:
(1) 匹配routes.IgnoreRoute命名空间的“{resource}.axd/{*pathInfo} ”网址格式。
(2) 匹配请求的URL的第1个部分,即“Member”,由于没有匹配到“{resource}.axd”,所以匹配失败。
(3) 跳转到routes.MapRoute命名空间的“{controller}/{action}/{id}”网址格式。
(4) 匹配请求的URL的第1个部分,即“Member”,并且匹配到{controller}参数。
(5) 匹配请求的URL的第2个部分,即“Detail”,并且匹配到{ action }参数。
(6) 接下来的“?id=123”就不算是网址的一部分了,所以它不会被算进到RouteValue表达式中,因此不会再对它进行匹配。
(7) “{id}”部分因为没有匹配到,所以会读取默认值,也就是“UrlParameter.Optional”部分。由于存在默认值,所以也算匹配成功。
(8) 因为所有的RouteValue表达式都匹配成功,所以这次的HTTP请求会由此网址路由提供服务。
匹配结果:
该网址使用routes.MapRoute命名空间进行处理,并通过MvcHandler将值赋予适当的Controller和Action程序。在这里会对应MemberController的Detail动作。
为网址路由加上限制条件:
MapRoute()是最常用来定义Routing规则的辅助方法,它其实还有许多应用方式(重载)。最常见的应用方式为“样式比对规则(正则表达式)+限制条件”,下面举例说明:
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Guestbook", action = "Index", id = UrlParameter.Optional }, // 参数默认值
new { id = @"\d+" }
);
我们在辅助方法中设置了第四个参数,这些参数指定了一个匿名对象,其中ID属性就是我们对比{id}路由值的限制条件,其限制条件使用正则表达式来表示,“\d+”表示路由值必须为
数字的时候才算比对成功,比如你的网址“http://localhost/Order/Member/Index/123abc”就会对比失败。