自强不息,厚德载物!身心自在,道法自然!


Asp.Net MVC 3 【URLs, Routing,and Areas】

这里我们就分享一些MVC框架原理上的东西,就从URL,路由机制等开始吧!关于MVC简单的介绍大家可以去下载我分享的视频或者自己去搜一些资料了解下,这就关于MVC基本介绍就不在罗嗦了!直接开始我们的URL路由部分。

简介路由体系

   MVC路由主要有两个功能:

             1. 检查传入的URL找出的对应的控制器(Controller)和方法(Action)请求。这就是MVC的路由体系处理我们客户端请求的目的。

             2. URL生成输出。这些URL中出现的HTML渲染特定操作时将调用用户单击链接(此时,它已成为一个再次传入的URL)。

我们开始创建一个项目("Routing"),用的是MVC应用程序是Internet Application模版。因为玩路由这些东东都在Global.asax文件里,所以在VS里打开该文件夹。默认的Global.asax文件如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Routing
{
    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
    // 请访问 http://go.microsoft.com/?LinkId=9394801

    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}", // 带有参数的 URL
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

Application_Start方法由底层的Asp.Net当应用程序的平台第一次启动时,使用RegisterRoutes方法注册路由。该方法的参数是静态RouteTable的属性。这是RouteCollection类的一个实例。接下来我们删除掉RegisterRoutes方法下的内容,因为我们要了解到他(URL模式)到底是怎么一回事,所以我们需要退一步,干掉这些默认(VS)自动创建的路由机制,用我们自己的配置来解开URL模式的真实面目。

简介URL模式

路由系统的工作原理它的魔力,使用了一套路由。这些路由,集体撰写的URL计划方案的应用程序,这是您的应用程序会识别和URL集回应。我们不需要手动输入所有单独的URL。相反,每个路由包含一个URL模式,这是比较传入的URL。如果模式匹配的URL,那么它是用来处理URL路由系统(机制)。譬如在之前的项目实战里,我们可以看到如下的URL:

                                               Http://mysite.com/Admin/Index

这是我们用来访问管理员的产品目录的URL。URL可以分解成几部分。这些URL的组成部分,不包括主机名和查询字符串,被/字符。URL的例子中,有两个部分,如下图1.

图1.第一部分包含Admin,第二部分包含Index。在我们眼里很明显第一部分涉及到的控制器(Controller)和第二部分涉及的动作或者说方法(Action)。当然,我们需要这种关系来表达的方式,路由系统可以明白了,那到底URL模式是不是如下所:

                                                      {controller}/{action}
处理传入的URL时,路由系统的工作是相匹配的URL模式,然后从URL中提取值段模式。段使用大括号({***}字符)表示变量。例如模式有两个分部变量名controller(控制器)和 Action(方法)。
我们说匹配模式,MVC应用程序,因为通常都会有多条路由航线,路由机制会比较传入的URL的各条路线的URL模式,直到它可以找到一个匹配。

默认情况下,一个URL模式将匹配任何URL正确数目的片段。对于示例,该示例将匹配任何模式的URL,有两个部分,如下表所示

请求的URL 细分变量
Http://mysite.com/Admin/Index

controller = Admin

action =Index

Http://mysite.com/Index/Admin

controller = Index

action =Admin

Http://mysite.com/Apples/Oranges

controller = Apples

action = Oranges

Http://mysite.com/Admin 会报错(段过少)
Http://mysite.com/Admin/Index/Soccer 会报错(段过多)

URL模式两个突出的关键行为:

  • URL模式是保守的,将匹配有相同的URL模式段的数量。
  • URL模式是自由的。如果一个URL确实有正确的段数, 模式将提取的值段变量,不管怎样。

这是默认的行为,这是了解URL模式运作的关键。

正如我们提到的,路由系统不知道任何关于MVC应用程序,这样的匹配URL模式,即使是没有控制器或动作对应的值提取从URL。你可以看到在表中的第二个例子证明了这一点。我们已调换在URL中的Admin和Index段,所以也一直从URL中提取的值调换。

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

若你有了一个URL模式的思想,你可以使用它来定义一个路线。打开我们的Global.asax文件,注册一个简单的路由,具体如下:

     public static void RegisterRoutes(RouteCollection routes)
        {
            Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            routes.Add("MyRoute", myRoute);
        }

这种方法是稍微更紧凑,主要是因为我们不需要创建一个实例MvcRouteHandler类。 MapRoutem方法是专为使用MVC应用程序。 ASP.NET网页窗体应用程序可以使用的MapPageRoute方法在RouteCollection类定义。运行我们的程序,结果如下图2.

图2.

我们的URL模式已处理的URL,并提取控制器(Controller)变量的值和Action(方法)变量指数。 MVC框架要求的指标方法对我们来说,这是我们选择了互联网应用的MVC项目时创建的主控制器模板。

定义默认值

我们得到一个错误时,我们要求应用程序是默认URL的,它匹配我们定义不确定的路线相。默认URL表示为〜/路由系统,所以有没有可以匹配的控制器和方法变量的分部。我们刚才解释的URL模式是保守的,他们将配合的网址指定号码段。我们也说,这是默认行为。改变这种情况的方法之一行为是使用默认值。默认值是当URL不包含段可以匹配的值。提供一个默认的路由具体代码如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            //提供默认路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });
        }

作为一个匿名类型的属性提供默认值。我们提供了一个指数的行动变量的默认值。这条航线将匹配所有两部分的网址,现在,我们提供了默认值的动作段,路线也将匹配单段以及网址。处理URL时,路由系统将提取的控制器值从单一的URL部分,并用行动变量的默认值。这样,我们可以要求的网址http://mydomain.com/Home和调用索引操作方法在主控制器的。运行结果如下图3.

图3.我们可以进一步定义不包含在所有的任何部分变量的URL,依托在刚刚 默认值来确定的行动和控制器。我们可以使用默认值的默认URL映射,具体代码如下:

     public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //提供方法和控制器默认值的路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
        }

通过定义提供方法和控制器的默认值的路由,我们可以直接访问http://mysite即可,运行效果如下图4.

图4.提供控制器和操作变量的默认值,我们已经创造了一个路线将匹配具有变量段为零的地址,一个变量端或两个变量段的部分,具体如下表:

段数 例子 映射
0 mydomain.com

controller = Home

action = Index

1 mydomain.com/Customer

controller = Customer

action = Index

2 mydomain.com/Customer/List

controller = Customer

action = Index

3 mydomain.com/Customer/List/All (会报错)段数过多

使用静态URL段

并非所有URL模式的细分需要变量。你还可以创建模式静态段。假设我们要匹配这样的网址,支持前缀为公共的URL:

                                                                      http://mydomain.com/Public/Home/Index

我们配置这样一条模式,具体代码如下:

     public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //提供方法和控制器默认值的路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
        }

这将匹配URL模式包含三个部分,第一,必须是客户的唯一地址。其他两部分可以包含任何值,将用于控制器和行动变量。然后运行访问我们Http://mysite/public/Home/Index,运行结果如下图5.

图5.

我们还可以创建URL模式,有段包含静态和可变因素,具体代码如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //提供方法和控制器默认值的路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");
        }

在这条路线的模式匹配任何两个分部的网址,其中第一部分开始字母X为控制器的开始,方法从第二部分。我们可以常识访问下面的URL将匹配路由:

http://mydomain.com/XHome/Index  ,运行结果如下图6.

图6.该URL将被定Home控制器上向到Action操作方法。

我们可以结合静态URL段和默认值创建一个特定的URL别名。如果你已经公开发表您的URL模式,并形成了一个与用户的合同可能是有用的。如果重构在这种情况下的应用程序,你需要保留以前的URL格式。打个比方吧!假如我们以前有一个Shop控制器,现在被Home控制器取代了我们如何才能创建一个路由维护旧的URL架构。我们可以用下面的办法,具体代码如下:

    public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            //提供方法和控制器默认值的路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
        }

我们已经添加的路由匹配任何两部分第一部分是Shop的URL。动作(Action)从第二个URL段值。 URL模式不包含的变量段控制器,所以我们提供的默认值使用。这意味着,(Action)动作上的要求被替代的控制器和现在控制器转换。我们可以更近一步,创建动作(Action)方法重构也不再是在目前的别名控制器。要做到这一点,我们只需创建一个静态的URL,并提供控制器和行动值默认值,具体代码如下:

 public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            //提供方法和控制器默认值的路由
            routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
        }

 通知,我们首先应以我们新的路由。这是因为具体路由的遵循。如果Shop/ OldAction的要求下进行处理定义路由,例如,我们会得到一个不同的结果和我们想要的结果。该请求将被处理使用404  - Not Found错误页面,而不是为了维护我们与用户之间合约。

 细分变量机制

我们不局限于只是控制器和行动变量。我们还可以定义自己的变量,具体代码如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            //额外的变量定义URL模式
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });
        }

路由的URL模式定义典型的控制器和(Action)动作变量,以及自定义变量名为id。这条路由将匹配任何零到三段的URL。第三内容段将被分配到id变量,如果没有第三部分,则默认值将是使用。我们可以使用RouteData.Values访问任何分部变量在操作方法属性。为了证明这一点,我们添加了一个方法在HomeController,在主控制器类叫做CustomVariable,具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Routing.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "欢迎使用 ASP.NET MVC!";

            return View();
        }

        public ViewResult CustomVariable()
        {
            this.ViewBag.CustomVariable = RouteData.Values["id"];
            return this.View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

我们添加相应的视图,具体代码如下:

@{
    ViewBag.Title = "CustomVariable";
}

<h2>Variable: @ViewBag.CustomVariable</h2>

如果您运行的应用程序浏览URL/Home/ CustomVariable/Hello,CustomVariable的在HomeController的方法被称为动作方法,自定义部分变量的值被检索从ViewBag和显示出来,结果如下图7.

图7.

使用自定义变量作为参数的操作方法

使用RouteData.Values属性,只有一个办法来访问自定义路由变量。另一种方法是更优雅。如果我们定义的参数名称与我们的操作方法相匹配的网址模式变量,MVC框架将通过从URL作为参数的操作方法获得的值。例如,自定义变量,在我们上面的路由被称为ID。我们可以修改的CustomVariable的操作方法,因此,它有一个匹配的参数,具体代码如下:

        //映射一个自定义URL段变量来一个动作方法参数
        public ViewResult CustomVariable(string id )
        {
            this.ViewBag.CustomVariable = this.Index();
            return this.View();
        }

当路由系统匹配对我们在我们配置的路由表定义的URL网址,价值在URL中的第三部分是分配给自定义变量的指数。 MVC框架的比较段与操作方法的参数列表变量列表,如果匹配的名字,通过从URL值的方法。我们已经定义了id参数为一个字符串,但MVC框架将尝试转换网址值到任何参数类型定义。如果我们宣布id参数为一个int或一个DateTime,然后,我们将收到从解析托安该类型的实例的URL值。这是一个优雅有用的功能,不再需要我们自己处理的转换。

定义可选的URL片段

一个可选的URL部分是一个用户不需要指定,但其中没有默认值是规定。我们指定段的变量是可选的设置默认值UrlParameter.Optional,具体代码如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            //指定一个可选的URL片段
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
        }

这条路由将匹配与否的ID段已提供的网址.下表描述这种路由用于不同的URL。(用一个可选的部分匹配url变量)

段数 例子 映射
0 mydomain.com controller= Home
action= Index
1 mydomain.com/Customer controller= Customer
action= Index
2 mydomain.com/Customer/List controller= Customer
action= List
3 mydomain.com/Customer/List/All controller= Customer
action= List
id = All
4 mydomain.com/Customer/List/All/Delete 会报错(段数过多)

正如你可以看到其外表,只有当有一个id变量被添加到组变量传入URL中的相应部分。要清楚,这不是id值是空的时,没有提供相应的段;相反,情况是,一个id变量没有被定义。如果你需要知道用户是否提供了有价值的东东,此功能非常有用。如果我们提供了一个id参数的默认值的操作方法,并获得该值,我们将无法告诉如果使用默认值或用户正好请求的URL中的默认值。可选段的一个常见的用途是强制执行的关注点分离,这样的默认值操作方法参数不包含在路由定义。如果你想按照此实践中,你可以使用的C#可选参数功能来定义你的操作方法参数,具体如下:

        //定义一个默认值为一个动作方法参数
        public ViewResult CustomVariable(string id = "DefaultId")
        {
            this.ViewBag.CustomVariable = id;
            return this.View();
        }

运行,结果如下图8.

图8.

定义变长的路由

改变URL模式的默认保守的另一种方法是接受可变数目的URL段。这可以让你任意长度在一个单一的路由,路由网址。您定义的支持做前缀的变量段指定段作为一个包含所有的变量之一,星号(*)。具体实例一个路由如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            //指定一个包括所有变量的路由
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
        }

我们变成路由,从前面的例子添加一个包括所有的细分变量,这是我们想象的包括所有的变量。现在,这条路由将匹配任何URL。前三段值,分别为控制器,动作和id变量。如果URL中包含额外段,他们都被分配到我们的包括有意变量段(也就是{*catchall})部分。这条路由可以匹配的URL如下表:

段数 例子 映射
0 mydomain.com controller= Home
action= Index
1 mydomain.com/Customer controller= Customer
action= Index
2 mydomain.com/Customer/List controller= Customer
action= List
3 mydomain.com/Customer/List/All controller= Customer
action= List
id = All
4 mydomain.com/Customer/List/All/Delete controller= Customer
action= List
id = All
catchall = Delete
5 mydomain.com/Customer/List/All/Delete/Perm controller= Customer
action= List
id = All
catchall = Delete/Perm

有段,在这条路线的URL模式匹配的数量没有上限。请注意,段由包扩所有捕获的形式段/段/段。我们是负责处理字符串打破了个别分部。

优先控制器名称空间

 当传入的URL匹配的路由,MVC框架的控制器变量的值寻找适当的名称。例如,当控制器变量的值是Home,然后看起来HomeController控制器的MVC框架。这是一个不合格的类名,这意味着,MVC框架并不知道怎么做,如果有两个或两个以上的类称为HomeController在不同的命名空间。当发生这种情况,将报告一个错误,如下图9:

图9.(你可以给项目在加一个HomeController)试试。

这个问题时,往往比较常见,特别是如果你在一个大的MVC工作从其他的开发团队或第三方供应商的控制器使用库的项目。这是自然命名有关用户帐户的AccountController例如,一个控制器,它仅仅是一个时间的问题之前,你遇到命名冲突。为了解决这个问题,我们可以告诉MVC框架,优先某些命名空间当试图解决的一个控制器类的名称,具体代码如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            //指定名称空间解析顺序
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
        }

我们作为一个字符串数组表示的命名空间。在程序运行后,我们已经告诉MVC框架看在URLsAndRoutes.Controllers命名空间之前,寻找到别的地方去。如果有合适的控制器不能被发现在该命名空间,然后将默认的MVC框架到其正常的行为,并看在所有可用的命名空间。名称空间添加到路线都具有同等的优先级。 MVC框架不检查第一个命名空间,然后再移动到第二等等。例如,假设我们添加了两个我们的项目命名空间的路线,代码如下面:

public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            //指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

        }

我们会看到如上图8同样的错误,因为MVC框架试图解决路由添加到命名空间,我们所有的控制器类的名称。如果我们想给优先在一个命名空间的单个控制器,但在另一个解决所在其他控制器命名空间,我们需要创建多条路由,具体代码如下:

 public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            //指定名称空间解析顺序
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            //使用多个路由控制名称空间解析
            routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });
        }

我们可以告诉MVC框架,只是看在我们指定的命名空间。如果一个匹配控制器不能被发现,然后框架将不会寻找其他地方。具体如下:

public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            //禁止依靠其他的命名空间
            Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            myRoute.DataTokens["UseNamespaceFallback"] = false;
        }

MapRoute方法返回一个Route对象。我们一直忽略在前面的例子,因为我们并不需要作出任何调整所创建的路线。要禁用搜索其他命名空间中的控制器,我们必须采取Route对象,并设置UseNamespaceFallback键的DataTokens集合属性为false。此设置将被传递给组件负责寻找控制器详细的后续在学习。

约束路由

我们描述了如何URL模式是保守他们如何匹配段和自由的他们是如何匹配的段的内容。前面已经解释保守主义控制的程度不同的技术(或许有些地方描述的不清错好着错误还请大家指教)路由符合更多或更少段使用默认值,可选的变量,依此类推。现在是时候来看看我们如何能够控制自由主义的匹配URL内容段如何限制的路由将匹配一组URL。一旦我们有控制权路由的行为,这些方面,我们可以创建URL表示的很精确。

约束路由使用一个正则表达式

我们看看如何使用正则表达式来约束路由,具体代码如下:

  public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            //约束路由使用一个正则表达式
            routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new { controller = "^H.*" },
                new[] { "URLsAndRoutes.Controllers"});
        }

我们通过MapRoute方法的参数定义约束。默认值一样,作为一个匿名类型,其中类型的属性对应的约束表示我们要约束段变量的名称。在这个例子中,我们用一个正则表达式匹配的URL只有在约束控制器变量的值开始字母H。

限制一个路由到一组特定的值

我们可以使用正则表达式限制路线,充分使用,只有特定的URL段值导致匹配。我们做到这一点使用竖线(|)字符,具体代码如下:

public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            //约束路由一个分部变量值的一组特定
            routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
               new { controller = "^H.*", action = "^Index$|^About$" },
               new[] { "URLsAndRoutes.Controllers" });
        }

这个约束将允许路由,以配合关于行动部分的值是唯一网址。约束被应用于在一起,这样的值的行动所施加的限制变量结合所施加的控制器上的变量。这意味着,只有当控制器变量一方面开始匹配动作变量匹配网址。所以,现在你可以看到,我们创造非常精确的路由。

限制使用HTTP方法的路由

我们可以限制路线,使它们匹配URL,只有当它使用一个特定的HTTP请求法,具体代码如下:

public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            ////约束路由一个分部变量值的一组特定
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new { controller = "^H.*", action = "^Index$|^About$" },
            //   new[] { "URLsAndRoutes.Controllers" });

            //基于约束路由HTTP方法
            routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
               new { controller = "^H.*", action = "Index|About" ,
               httpMethod = new HttpMethodConstraint("GET")},
               new[] { "URLsAndRoutes.Controllers" });
        }

指定HTTP方法约束的格式是有点奇怪。不要紧,叫什么名字我们给出属性,只要我们分配的的HttpMethod约束类的实例,我们称之为我们的约束属性httpMethod,以帮助区分它的价值为基础的限制。我们通过HTTP方法的名称,我们要支持字符串参数的构造HttpMethod约束类。而且限制了路由GetRequests要求,但我们可以有容易添加其他方法的支持,具体如下:

... 
httpMethod = new HttpMethodConstraint("GET", "POST") }, 
... 

定义一个自定义约束

如果标准的约束不能满足你的需求,您可以定义您自己的自定义约束通过实现IRouteConstraint接口(给项目添加一个来定义类),具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;

namespace Routing.Infrastructure
{
    public class UserAgentConstraint : IRouteConstraint
    {
        private string requiredUserAgent;

        public UserAgentConstraint(string agentParam) 
        {
            this.requiredUserAgent = agentParam;
        }

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
        {
            return httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(this.requiredUserAgent);
        }
    }
}

IRouteConstraint接口定义一个实现可以使用Match方法,显示路由系统,如果它的约束条件已得到满足。匹配方法的参数提供访问请求从客户端,正在评估的路线,参数名称的约束,该段从URL中提取的变量,并请求是否是细节检查传入或传出的URL。对于我们的例子中,我们检查的UserAgent属性值客户端的请求,看它是否包含一个值传递给我们的构造。下面显示了我们自定义约束的路由,具体配置如下:

   public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            ////约束路由一个分部变量值的一组特定
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new { controller = "^H.*", action = "^Index$|^About$" },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////基于约束路由HTTP方法
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new
            //   {
            //       controller = "^H.*",
            //       action = "Index|About",
            //       httpMethod = new HttpMethodConstraint("GET")
            //   },
            //   new[] { "URLsAndRoutes.Controllers" });
            //应用自定义约束的路由
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new
            {
                controller = "^H.*",
                action = "Index|About",
                httpMethod = new HttpMethodConstraint("GET", "POST"),
                customConstraint = new UserAgentConstraint("IE")
            },
            new[] { "URLsAndRoutes.Controllers" });
        }

我们已经限制了路由,这样它会匹配来自浏览器的唯一请求其用户代理字符串包含IE浏览器,其中包括来自微软浏览器的请求。

路由请求磁盘文件

不是所有MVC应用程序的要求是控制器和行动。我们仍然需要以服务的方式内容,如图像,静态HTML文件,JavaScript库,等等。作为例子,我们有创建一个文件称为StaticContent.html在我们的例子MVC应用程序的内容文件夹。StaticContent.html代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Static HTML Content</title>
</head>
<body>
This is the static html file (~/Content/StaticContent.html)
</body>
</html>

路由系统提供集成支持服务等内容。如果您启动应用程序请求的URL/Content/StaticContent.html的,你会看到这个简单的HTML文件的内容显示在浏览器如下图9所示。

图9.

默认情况下,路由系统的检查,看看如果URL匹配磁盘文件前评估应用程序的路由。然后在磁盘上的文件送达,从来没有使用过的路由。我们可以扭转这一行为,使我们的路由是评估前检查磁盘上的文件通过设置RouteExistingFiles属性RouteCollection为true,具体代码如下:

public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            ////约束路由一个分部变量值的一组特定
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new { controller = "^H.*", action = "^Index$|^About$" },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////基于约束路由HTTP方法
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new
            //   {
            //       controller = "^H.*",
            //       action = "Index|About",
            //       httpMethod = new HttpMethodConstraint("GET")
            //   },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////应用自定义约束的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            //启用路由之前评估文件检查
            routes.RouteExistingFiles = true;
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new
            {
                controller = "^H.*",
                action = "Index|About",
                httpMethod = new HttpMethodConstraint("GET", "POST"),
                customConstraint = new UserAgentConstraint("IE")
            },
            new[] { "URLsAndRoutes.Controllers" });
        }

该公约是把这个声明保持着密切的RegisterRoutes方法,虽然它将生效,即使你把它设置后,您已经定义了的路由。一旦属性已设置为true,我们可以定义匹配的URL对应的磁盘文件的路由,具体代码如下:

 public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            ////约束路由一个分部变量值的一组特定
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new { controller = "^H.*", action = "^Index$|^About$" },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////基于约束路由HTTP方法
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new
            //   {
            //       controller = "^H.*",
            //       action = "Index|About",
            //       httpMethod = new HttpMethodConstraint("GET")
            //   },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////应用自定义约束的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            ////启用路由之前评估文件检查
            //routes.RouteExistingFiles = true;
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            //一个路由的URL模式对应于一个磁盘文件
            routes.RouteExistingFiles = true;
            routes.MapRoute("DiskFile", "Content/StaticContent.html", new { controller = "Account", action = "LogOn" },
                new { customConstraint = new UserAgentConstraint("IE") });
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new
            {
                controller = "^H.*",
                action = "Index|About",
                httpMethod = new HttpMethodConstraint("GET", "POST"),
                customConstraint = new UserAgentConstraint("IE")
            },
            new[] { "URLsAndRoutes.Controllers" });
        }

这条路由映射请求的URL Content/StaticContent.html的登录动作帐户控制器。我们增加了一个约束的路由,这意味着它只会匹配从浏览器的用户代理字符串的请求。

当RouteExistingFiles属性已启用磁盘上的文件将只提供给客户,如果有有匹配的路由请求。对于我们的例子路由,这意味着IE浏览器的用户将从Account控制器的响应,虽然所有其他用户将看到的静态内容。运行如下图10。

图10.

回避路由机制

设置的RouteExistingFiles属性,这是我们在上面展示,使得路由机制更具包容性。现在我们需要会绕过路由机制评估对我们定义的路由此功能相对应的是能力,使路由机制的包容性和防止URL从回避我们正在评估对路由。为此,我们使用的IgnoreRoute方法在RouteCollection类。具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Routing.Infrastructure;

namespace Routing
{
    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
    // 请访问 http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            //Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            //routes.Add("MyRoute", myRoute);

            ////提供默认路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });

            //别名的一个控制器和一个方法
            routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });

            //混合静态URL段和默认值
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });

            //配置混合段的URL模式
            routes.MapRoute("", "X{controller}/{action}");

            ////提供方法和控制器默认值的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });

            //配置静态段的URL模式
            routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

            ////额外的变量定义URL模式
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });

            ////指定一个可选的URL片段
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定一个包括所有变的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            ////指定名称空间解析顺序
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers", "AdditionalControllers" });

            ////使用多个路由控制名称空间解析
            //routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "AdditionalControllers" });

            ////禁止依靠其他的命名空间
            //Route myRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
            //myRoute.DataTokens["UseNamespaceFallback"] = false;

            ////约束路由使用一个正则表达式
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //    new { controller = "^H.*" },
            //    new[] { "URLsAndRoutes.Controllers"});

            ////约束路由一个分部变量值的一组特定
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new { controller = "^H.*", action = "^Index$|^About$" },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////基于约束路由HTTP方法
            //routes.MapRoute("MyRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //   new
            //   {
            //       controller = "^H.*",
            //       action = "Index|About",
            //       httpMethod = new HttpMethodConstraint("GET")
            //   },
            //   new[] { "URLsAndRoutes.Controllers" });

            ////应用自定义约束的路由
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            ////启用路由之前评估文件检查
            //routes.RouteExistingFiles = true;
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            ////一个路由的URL模式对应于一个磁盘文件
            //routes.RouteExistingFiles = true;
            //routes.MapRoute("DiskFile", "Content/StaticContent.html", new { controller = "Account", action = "LogOn" },
            //    new { customConstraint = new UserAgentConstraint("IE") });
            //routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            //    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            //new
            //{
            //    controller = "^H.*",
            //    action = "Index|About",
            //    httpMethod = new HttpMethodConstraint("GET", "POST"),
            //    customConstraint = new UserAgentConstraint("IE")
            //},
            //new[] { "URLsAndRoutes.Controllers" });

            //使用IgnoreRoute方法
            routes.RouteExistingFiles = true;
            routes.MapRoute("DiskFile", "Content/StaticContent.html", new { controller = "Account", action = "LogOn" },
                new { customConstraint = new UserAgentConstraint("IE") });
            //忽略给定路由表约束列表指定的URL
            routes.IgnoreRoute("Content/{filename}.html");
            routes.MapRoute("", "{controller}/{action}");
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new
            {
                controller = "^H.*",
                action = "Index|About",
                httpMethod = new HttpMethodConstraint("GET", "POST"),
                customConstraint = new UserAgentConstraint("IE")
            },
            new[] { "URLsAndRoutes.Controllers" });
        }protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

我们可以使用像{filename}的部分变量的URL匹配的范围。在这种情况下,URL模式将匹配任何两部分,第一部分是内容的URL和第二个内容.html扩展。IgnoreRoute方法创建条目,其中的路由处理程序是在RouteCollection实例的StopRoutingHandler类,而不是MvcRouteHandler。路由系统是硬编码的,以识别这个处理程序。如果URL传递给IgnoreRoute模式匹配方法,然后没有路由将被评估,就像当一个普通的路由匹配时。因此,我们把调用IgnoreRoute方法的看是重要的.  OK关于路由这里先分享一到这里,感觉路由这东西还是挺大的,分享的话貌似还有好多东西。文章写的长,估计也有描述不正确或者错误的地方,还请路过的前辈们多多指教,大家共同学习。谢谢!

posted @ 2012-07-18 09:56  辉太  阅读(3232)  评论(8编辑  收藏  举报

路漫漫其修远兮,吾将上下而求索!