65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC3 中的路由

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (16投票s)

2012年6月21日

CPOL

7分钟阅读

viewsIcon

55588

MVC 中路由的简要介绍。

引言

很多人都在问我 MVC 中的路由是如何工作的,所以这篇文章将为大家简要介绍一下。 

路由系统可以分为两个部分

  1. RouteData:这个机制用于检查传入的 URL,然后决定请求需要发送到哪个控制器和操作。
  2. VirtualPath:这个机制负责生成出站 URL。这些 URL 出现在我们视图渲染的 HTML 中,以便用户点击链接时可以调用特定的操作。 

在本文中,我们将只关注 RouteData。要学习 MVC3 的基础知识,请阅读以下文章 点击此处

让我们开始创建一个路由项目 

使用 Internet 模板创建一个新的 MVC 应用程序,命名为 Routing。因为我们选择了这个模板,所以它会包含一些预先编写好的路由。

由于路由定义在 Global.asax 中,打开该文件,您会看到以下代码行

namespace Routing
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
        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();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

我们可以看到 Application_Start 方法负责调用 RegisterRoutes 方法,该方法定义了路由规则。当应用程序启动时,ASP.NET 平台会调用这个 Application_Start 方法。 

注意: 幸运的是,MVC 允许我们定义每个路由需要遵循的 URL 模式,而不是手动输入所有单独的 URL。如果路由的模式匹配 URL,那么它就会被处理。

让我们来看一个简单的 URL。如果您在不删除当前路由的情况下运行应用程序,然后打开https://:xxxx/Home/About,您会看到以下屏幕

让我们快速讨论一下。 URL 可以分解为段。这些是 URL 的组成部分(不包括主机名和查询字符串),由 / 字符分隔。在示例 URL 中,有两个段

  1. Home – 这是 URL 的第一个段,指向 Home 控制器。
  2. About - 这是 URL 的第二个段,指向 About 操作。 

URL 模式是 {controller}/{action}

在处理传入的 URL 时,路由系统的任务是将 URL 匹配到模式,然后从 URL 中找出段变量的值。段变量使用花括号({ 和 } 字符)表示。我们的示例有两个名为 controller 和 action 的段变量。

我们说匹配到模式,是因为 MVC 应用程序。

现在让我们快速看看这个路由可以处理的所有情况。 

请求 URL 段变量
http://testsite.com/Home/Indexcontroller = Home, action = Index 
http://testsite.com/Index/Homecontroller = Index, action = Home
http://testsite.com/Home不匹配  (段太少)
http://testsite.com/Home/Index/Soccer不匹配  (段太多)

正如我们所见,在第一种和第二种情况下,URL 模式匹配了正确的段数,并且我们可以到达相应的控制器和操作,而在第三种和第四种情况下,URL 模式不匹配。 

这是默认行为,很快我们将学习如何更改默认设置。

创建和注册一个简单的路由

由于我们是从基础开始,暂时删除 RegisterRoutes 方法的内容,我们将逐步学习如何编写路由。

一旦您有了 URL 模式,就可以用它来定义一个路由。

现在让我们创建一个自定义路由来处理上面的例子 

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}");
}

在这里,我们创建了一个名为 CustomRoute 的新路由,它将把 URL 段分别处理到指定的控制器和操作。

例如

URL http://testsite.com/Home/Index 将路由到 controller = Home 和 action = Index

定义默认值 

上面定义的路由在第一种和第二种情况下都能正常工作,但如果我们需要确保第三种情况也能正常工作呢?为了做到这一点,我们需要为视图定义默认值,如下所示:

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute ", "{controller}/{action}", new { action = "Index" });
}

这个路由告诉我们,如果我们不为 Action 提供任何值,它将默认调用 Index 操作,这意味着 URL http://testsite.com/Home/ 将路由到 controller = Home 和 action = Index,因为没有指定其他操作。同时,URL http://testsite.com/Home/Xyz 将路由到 controller = Home 和 action = Xyz,因为它被明确指定了。

接下来想到的是,如果我们希望在缺少默认控制器时也执行一个默认控制器,是的,我们可以通过以下方式处理:

public static void RegisterRoutes(RouteCollection routes) {
     routes.MapRoute("CustomRoute ", "{controller}/{action}", new { controller = "Home", action ="Index" });
}

通过为 controller 和 action 变量都提供默认值,我们创建了一个可以匹配零个、一个或两个段的 URL 的路由。下表概述了其行为 

请求 URL  段变量
http://testsite.com/ controller = Home, action = Demo
http://testsite.com/Homecontroller = Home, action = Demo
http://testsite.com/Demo/Testcontroller = Demo, action = Test
http://testsite.com/Test/Demo controller = Test, action = Demo
http://testsite.com/Test/Demo/List不匹配 (段太多) 

静态 URL 段 

还可以创建具有静态段的模式。假设您有一个需求,希望在 URL 前加上“Student”一词。 

http://testsite.com/Student/Home/Index  

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute ", "{controller}/{action}", 
                       new { controller = "Home", action = "Index" });
      routes.MapRoute("StaticRoute", " Student /{controller}/{action}", 
                       new { controller = "Home", action = "Index" });
}

此 URL 模式将仅匹配包含三个段的 URL,其中第一个段必须是 Student。另外两个段可以包含任何值,并将用于 controller 和 action 变量。  

我们还可以创建包含静态和变量元素的 URL 模式。 

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("StaticRoute ", "XYZ{controller}/{action}"); 
      routes.MapRoute("CustomRoute ", "{controller}/{action}", 
                      new { controller = "Home", action = "Index" });
      routes.MapRoute("AnotherStaticRoute ", "Public/{controller}/{action}",
                      new { controller = "Home", action = "Index" });
}

此路由中的模式匹配任何两个段的 URL,其中第一个段以 XYZ 开头。controller 的值取自第一个段,不包括 XYZ。action 值取自第二个段。

例如,以下 URL 将被该路由匹配

http://testsite.com/XYZ/Home/Index 

此 URL 将被定向到 Home 控制器的 Index 操作方法。 

自定义段变量 

MVC 不仅限于将 URL 路由到 controller 和 action 变量。我们还可以自由定义自己的变量,例如 

public static void RegisterRoutes(RouteCollection routes) { 
      routes.MapRoute("CustomRoute ", "{controller}/{action}/{id}",
             new { controller = "Home", action = "Index", id = "DefaultId" }); 
} 

此路由将匹配任何零到三个段的 URL。第三个段的内容将被分配给 id 变量,如果不存在第三个段,则使用默认值。

现在我们首先想到的是如何获取这个值并使用它。 

所以,首先我们来谈谈如何获取这个 id 值,可以通过以下两种方式实现

  • 我们可以通过 RouteData.Values 属性在操作方法中访问任何段变量,因此 id 可以这样访问:
  • public ViewResult CustomVariable() {
          ViewBag.CustomVariable = RouteData.Values["id"];
          return View();
    }
  • 我们可以为操作方法定义参数,其名称与 URL 模式变量匹配,MVC 框架会将从 URL 中获取的值作为参数传递给操作方法。
  • public ViewResult CustomVariable(string id) {
          ViewBag.CustomVariable = index;
          return View();
    }

现在,一旦我们获取了 id 值,就可以像这样在视图中显示它:

@{
ViewBag.Title = "CustomVariable";
}
<h2>Variable: @ViewBag.CustomVariable</h2> 

定义可选 URL 段 

MVC 还允许我们拥有可选的 URL 段,这意味着用户不需要指定一个 URL 段,但即使没有为其指定默认值。

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}/{id}",
                   new { controller = "Home", action = "Index", id = UrlParameter.Optional });
} 

无论是否提供了 id 段,此路由都将匹配 URL。 

段数  URL 映射
http://testsite.com/ controller = Home, action = Demo
http://testsite.com/Testcontroller = Home, action = Demo
http://testsite.com/Test/Democontroller = Test, action = Demo
http://testsite.com/Test/Demo/List controller = Test, action = Demo, id = list
http://testsite.com/Test/Demo/List/NameId不匹配 (段太多) 

定义可变长度路由 

到目前为止,我们已经看到了如何处理任意特定数量的段的路由,但如果我们想处理“n”个段的情况呢?

MVC 也为我们轻松处理这种情况提供了支持。可以通过将其中一个段变量指定为“catchall”来支持可变段,方法是在其前面加上星号 (*)。

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}/{id}/{*catchall}",
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}    

如果您注意到这里,我们扩展了之前示例中的路由,添加了一个 catchall 段变量,我们形象地称之为 catchall。这个路由现在将匹配任何 URL。前三个段用于分别设置 controller、action 和 id 变量的值。如果 URL 包含其他段,它们都将被分配给 catchall 变量。

段数 URL 映射
http://testsite.com/ controller = Home, action = Demo 
http://testsite.com/Test controller = Home, action = Demo
http://testsite.com/Test/Demo controller = Test, action = Demo 
http://testsite.com/Test/Demo/List controller = Test, action = Demo, id = list 
http://testsite.com/Test/Demo/List/NameId/ProfIdcontroller = Test, action = Demo, id = list, catch = NameId/ ProfId

此路由中的 URL 模式可以匹配的段数没有上限。  

© . All rights reserved.