MVC 路由介绍

我们新建一个ASP.NET MVC Web程序的时候,会生成一个Global.asax文件。如下:

技术分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using System.Web.Routing;
 7 
 8 namespace KKX
 9 {
10     // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
11     // 请访问 http://go.microsoft.com/?LinkId=9394801
12 
13     public class MvcApplication : System.Web.HttpApplication
14     {
15         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
16         {
17             filters.Add(new HandleErrorAttribute());
18         }
19 
20         public static void RegisterRoutes(RouteCollection routes)
21         {
22             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
23 
24             routes.MapRoute(
25                 "Default", // 路由名称
26                 "{controller}/{action}/{id}", // 带有参数的 URL
27                 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
28             );
29 
30         }
31 
32         protected void Application_Start()
33         {
34             AreaRegistration.RegisterAllAreas();
35 
36             RegisterGlobalFilters(GlobalFilters.Filters);
37             RegisterRoutes(RouteTable.Routes);
38         }
39     }
40 }
View Code

Application_Start()是Web应用程序启动的时候的入口。

RegisterGlobalFilters()方法是用来注册全局筛选器的,与本篇内容关系不大。

RegisterRoutes()方法是用来注册路由表的。

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

IgnoreRoute()RouteCollection路由表类的扩展方法,用于忽略指定的路由请求。这句意思是忽略对扩展名为.axd文件的请求。

            routes.MapRoute(
                "Default", // 路由名称
                "{controller}/{action}/{id}", // 带有参数的 URL
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
            );

MapRoute()一个添加路由映射的方法(RouteCollection的扩展方法),这里是他最常用的一种重载,映射指定的URL路由并设置默认路由值:

     1. "Default"是路由的名称,这个名称在应用程序的路由的集合(routes对象)中是唯一的,如果重名生成时就会报错。

     2. "{controller}/{action}/{id}"代表的是路由的 URL表达式

     3. new { controller = "Home", action = "Index", id = UrlParameter.Optional } 声明了一个包含路由值的object匿名对象。这条语句添加了一条路由规则,将URL表达式映射到一个路由值-指向某个Controller下的某个Action方法。

 

发布网站的时候Global.asax文件会被编译成DLL。程序启动的时候就会首先调用Application_Start()方法, 

执行RegisterRoutes(RouteTable.Routes)语句后,路由表就完成注册了,默认路由规则开始生效。

有了这条默认规则,我们就可以使用/controllername/actionname?querystring=...这样的相对URL来调用程序中的每个action方法。

 

如何来定义一条URL表达式:

  首先URL表达式都是相对的,不包括主机域名部份(比如http://www.xxx.com)。{}保存的是占位符,“/”,“.”则用来作为分隔符,什么都有没则是静态内容:

  • URL /category/showcategory/1000  匹配 "{controller}/{action}/{id}"。
  • URL /product/2012/4/28.html         匹配  “/product/{year}/{month}/{day}.html”  ,诸如此类。

  这里需要注意的是{controller}和{action}是保留的两个占位符,分别代表对应的控制器名称和操作名称。

  {controller}对应控制器的名称,这里规定是控制器全名去掉Controller后缀的部份,CategoryController即Category

  {action}对应控制器内的Action方法的名称。

 

路由有两种不同的操作:

  获取路由值,当你在浏览器输入一个URL时,程序会在我们添加的路由表中通过对比URL表达式进行匹配,找到对应路由值。

    我们来看一个例子,我们来添加两条路由规则。

routes.MapRoute("Test", "where-are-you-going", new { controller = "Home", action = "Index" });
routes.MapRoute("Test1", "where-are-you-going", new { controller = "Home", action = "Others" });

     假设HomeController里有两个Action 分别是Index()Others()。

  各位觉得在浏览器输入http://www.xxx.com/where-are-you-going 哪个方法会被调用呢?如果上下颠倒一下呢?

  <调用HomeController.Index()/颠倒后调用HomeController.Others>

 

  获取URL,下面这段代码就使用Url.Action方法通过ControllerAction名完全限定了一个URL,

  即我们有了一个路由值,通过在路由表中匹配,可以找到对应的URL模式,进而生成一个URL

<a href="@Url.Action("Index", "Home")">主页</a>

     现在我们在默认的路由规则下再添加一条如下的路由规则

routes.MapRoute("MyHome", "myhome/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

上面的问题大家可以自己尝试一下,很明显,路由的匹配是 自上而下 的,只要匹配到第一条记录,就会返回对应URL或者路由值。这一点非常重要。很多人在定制路由规则的时候,总是发现自己的规则不生效。那么你就应该检查是不是被前面的路由覆盖掉了。

 

从这个站的URL可以看出,http://www.xxx.com/category/showcategory?categoryid=1000&view=list&orderby=price&page=1,用的应该只是默认路由规则,

可以推断出有一个名为Category的控制器,其中有个方法名为ShowCategory,必选参数为categoryid,其他为可选参数。

routes.MapRoute("Category", "category/{categoryid}", new { controller = "Category", action = "ShowCategory" }

这时候一定要注意喔,不要写在默认路由的下面,你懂得。不然你就悲剧了。

 

一般情况下我们建议如果你需要使用Globel文件来定制路由,请删除最初的默认路由,并给每一个Action定制自己的路由。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。