• 浅谈MVC中路由


    引言

      学习ASP.NET MVC 路由这一关是肯定必不可少的。这一节,我们就来简单介绍下MVC中的路由机制。简单的路由机制相信大家都已了解,这一节主要介绍路由中很少使用的部分。

    使用静态URL片段

      在一个路由中,并不是所有的URL片段都要求是动态的,也可以创建具有静态片段的模式。例如以下的路由:

    1 routes.MapRoute("StaticRoute", "X{controller}/{action}",
    2                             new { controller = "Home", action = "Index" },
    3                             new string[] { "MyFirstMvcProject.Controllers" });

      我们看到这条路由定义了第一个片段以字母X打头,controller的值是X字母以后的部分,第二个片段Action定义了默认值Index。这条路由将匹配任何X字母开头,controller值是取自第一个片段除字母X以外的部分。

      一个有趣的例子:

      设想下这样的场景,如果您的网站已经发布好久了,用户与网站之间已经形成了某种契约。例如。用户对于这个地址已经非常熟悉http://www.asp.net-example.com/Learn/Index。那么很显然控制器是Learn。如果现在您需要对程序进行重构,那么我们最好保留用户已经熟悉的链接地址。假设重构以后,新的控制器是Home。那么我们可以通过一条保留旧有URL地址的路由来实现这个功能。

    1 routes.MapRoute("StaticRoute", "Learn/{action}",
    2                             new { controller = "Home", action = "Index" },
    3                             new string[] { "MyFirstMvcProject.Controllers" });

      上面的路由,我们输入Learn/Index时,路由机制会自动匹配新的控制器Home。这样一方面没有打断网站与已有用户之间形成的契约,同时又对程序功能做了一个较好的迁移。我们在浏览器中运行如下:

      我们看到,我们输入/Learn/Index。路由找到的是HomeController。

    定义可变长路由

      我们通过定义可变长度的路由来匹配任意长度的URL。我们通过设置一个*catchall片段变量可以定义对可变片段数量的支持。请看下面的路由

    1 routes.MapRoute(
    2                 name: "Default",
    3                 url: "{controller}/{action}/{id}/{*catchall}",
    4                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    5                 namespaces: new[] { "MyFirstMvcProject.Controllers" }
    6             );

      我们来看下面的例子:

       从这个例子我们看出,我们输入的URL是Home/Index/Id/Do/Operation。我们通过{*catchall}片段变量来获取URL中的片段。我们看到catchall获取的是Do/Operation。说明任意长度的片段变量我们都可以获取到。只是在后续处理时,我们需要自行处理诸如Do/Opeartion这样的片段变量。

     按命名空间来区分控制器执行顺序

      从上面一个例子我们看到我们在路由里面设置了namespaces属性的值。如果我们不设置呢?看看会发生上面。请看下面的例子。

      我们看到,我们的项目中存在两个HomeController控制器,浏览器路由机制解析出控制器名称是Home后,两个名称是Home的控制器,MVC框架不知道选择哪一个。这种情况下,我们需要设置下路由器的namespaces属性。这样MVC就会优先从这个命名空间下去寻找控制器。

    定义自定义约束

      MVC框架默认给我们提供了根据正则表达式和HTTP方法来约束路由。如果这些方法还是无法满足要求的话,我们可以通过实现IRouteConstraint接口来自定义路由约束。我们首先来看下IRouteConstraint的情况。

     1         // 摘要: 
     2         //     确定 URL 参数是否包含此约束的有效值。
     3         //
     4         // 参数: 
     5         //   httpContext:
     6         //     一个对象,封装有关 HTTP 请求的信息。
     7         //
     8         //   route:
     9         //     此约束所属的对象。
    10         //
    11         //   parameterName:
    12         //     正在检查的参数的名称。
    13         //
    14         //   values:
    15         //     一个包含 URL 的参数的对象。
    16         //
    17         //   routeDirection:
    18         //     一个对象,指示在处理传入请求或生成 URL 时,是否正在执行约束检查。
    19         //
    20         // 返回结果: 
    21         //     如果 URL 参数包含有效值,则为 true;否则为 false。
    22         bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);    

      我们看到,这个接口就一个方法Match。MVC路由在匹配路由时会调用这个Match方法看请求的URL与当前路由是否匹配。下面我们还是通过一个例子来看一下把。请看以下例子:

     1 public class UserAgentConstraint : IRouteConstraint
     2     {
     3         private string requestUserAgent;
     4 
     5         public UserAgentConstraint(string userAgent)
     6         {
     7             this.requestUserAgent = userAgent;
     8         }
     9 
    10         public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    11         {
    12             bool result = (httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(this.requestUserAgent));
    13             return result;
    14         }
    15     }

      我们写一条全新的路由来测试下,看看效果。如下:

    1 routes.MapRoute("chromeRoute", "{controller}/{action}",
    2                             new { controller = "Home", action = "Index" },
    3                             new { customConstraint = new UserAgentConstraint("Chrome") });

      这条路由使用了我们自定义的约束路由机制,我们看到我们传递了Chrome给自定义的路由匹配器。这样火狐浏览器和IE应该没法进行浏览,谷歌是可以的。打开浏览器试一下。

      我们使用火狐浏览器来访问/Home/Index。会出现404的问题。

       而我们使用谷歌浏览器访问时,是可以正常进行访问的。

    对磁盘文件进行路由

      我们知道对于所有的请求并不是都是针对控制器和动作的。也有很多是对静态文件的访问。例如图像,样式文件,JS代码文件等。默认情况下,路由系统在评估应用程序的路由之前,会考察一个URL是否匹配一个磁盘文件。如果匹配,该文件会用来对该请求进行服务。应用程序定义的路由就不会被使用。

      我们可以通过设置routes.RouteExistingFiles = true来对MVC的默认机制进行修改。通过设置为true,意味着对已存在文件也进行路由。为了演示例子,我们还需要配置应用程序服务器,告诉IIS Express以便在请求到达MVC路由系统之前,不要拦截对磁盘文件的请求。请看下面的配置。

    1 <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />

      找到这一配置节点,将preCondition设置为""即可。

      这时候我们在浏览器中输入Content/CustomerJS.js会看的下面这一幕。

      我们看到,我们启用了对磁盘文件进行路由,这样MVC路由系统会设法找到名称为Content的控制器,这显然不是我们想要的。我们可以通过设置默认值来修复这个问题。

    1 routes.MapRoute("StaticRoute", "Content/CustomerJS.js",
    2                             new { controller = "Home", action = "Index" },
    3                             new string[] { "MyFirstMvcProject.Controllers" });

    绕过路由系统

      通过使用routes.IgnoreRoute("Content/{filename}.js")我们可以对Content文件夹下的JS文件不进行路由,这样我们上面例子的时候,就会展示JavaScript代码了。

  • 相关阅读:
    Epic OA Day2 2014/11/7
    LeetCode day15 2014/11/3
    LeetCode day14 2014/11/2
    Bluetooth BQB PTS(Profile Tuning Suite)
    音频编码:ADPCM
    软件推荐 : USB Over Network
    IOS的BLE蓝牙连接参数限制
    python pyinstaller
    QCC3003x BLE 设置私有地址
    QCC300x UART
  • 原文地址:https://www.cnblogs.com/dreamGong/p/5106732.html
Copyright © 2020-2023  润新知