• 第二节:各种路由约束(动态路由、静态路由、组合路由、正则约束、命名空间约束、区域内路由)


    一. 什么是路由

       路由是约束URL的一组规范,那么什么是URL呢?通俗的来说URL是一个地址,通过该地址,用户可以访问Web网站或者下载服务器上的文件。

         比如下面就是两组URL:

        http://www.cnblogs.com/yaopengfei/p/7828441.html

        http://www.cnblogs.com/yaopengfei/p/7828441

      显然我们喜欢第二组,省略.html,会使该地址看起来更加简洁,更加友好,利于SEO优化。

      那么我们怎么实现这个简单的需求呢?

      答案是:通过【路由】配置,所以现在我们似乎有点清晰了,路由可以规定URL的特殊格式,使其达到特殊效果。

      在ASP.NET MVC框架中,通过路由配置URL,使用户的URL请求可以映射到Controller下的action方法中,执行相应操作,并接受URL中传过来的参数,在MVC5框架中,在【RouteConfig.cs】类中进行路由规则的配置,如下图:

        

    二. 从源码的角度分析路由

       我们进入【RouteConfig】类中,发现核心代码是调用【RouteCollection】类下的MapRoute方法,F12看源码得知,MapRoute方法是RouteCollectionExtensions类的给【RouteCollection】类扩展方法的方法,并且有多个重载,如下图:

      下面分析一下参数的含义:

        (1) name:  要映射的路由的名称。

        (2) url:  路由的 URL 模式,可以自定义路由的格式,可以写静态路由,也可以写动态路由、组合路由等。

        (3) defaults:  一个包含默认路由值的对象,书写路由的默认值。

        (4) constraints: 一组表达式,可以使用正则指定 url 参数值的约束。

        (5) namespaces: 应用程序的一组命名空间,可以缩小检索路由对象匹配的范围。

      底层源码,有兴趣可以看一下:

     1  public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
     2         {
     3             if (routes == null)
     4             {
     5                 throw new ArgumentNullException("routes");
     6             }
     7             if (url == null)
     8             {
     9                 throw new ArgumentNullException("url");
    10             }
    11             Route route = new Route(url, new MvcRouteHandler()) {
    12                 Defaults = CreateRouteValueDictionaryUncached(defaults),
    13                 Constraints = CreateRouteValueDictionaryUncached(constraints),
    14                 DataTokens = new RouteValueDictionary()
    15             };
    16             ConstraintValidation.Validate(route);
    17             if ((namespaces != null) && (namespaces.Length > 0))
    18             {
    19                 route.DataTokens["Namespaces"] = namespaces;
    20             }
    21             routes.Add(name, route);
    22             return route;

    三. MVC中的几类路由及其规则

    1. 动态路由

    1        routes.MapRoute(
    2                 name: "Default",    //路由名称
    3                 url: "{controller}/{action}/{id}",   //路由规则
    4                 defaults: new { controller = "First", action = "Index1", id = UrlParameter.Optional }  //默认值,当Controller或action为空(省略)的时候调用
    5             );

    分析:路由规则为 {controller}/{action}/{id} ,其中 {controller}、{action}、{id}为三个参数,/ 为格式分割符号,defaults中声明的是默认路由,所以下面的测试结果:

    http://localhost:7559/

    http://localhost:7559/First

    http://localhost:7559/First/index1

    http://localhost:7559/First/Index1/2

    都会跳转到Index1的页面。

      变种:将上面的代码的URL分割符号稍微调整一下

    1        routes.MapRoute(
    2                name: "Default9",    //路由名称
    3                url: "{controller}/{action}-{id}",   //路由规则
    4                defaults: new { controller = "First", action = "Index1", id = UrlParameter.Optional }  //默认值,当Controller或action为空(省略)的时候调用
    5            );

      请求地址就变成了:

    http://localhost:7559/                                               【无法访问】

    http://localhost:7559/First                                        【404找不到】

    http://localhost:7559/First/index1                            【404找不到】

    http://localhost:7559/First/Index1-1                         【可以访问】

     

    2. 静态路由

    1         routes.MapRoute(
    2                 name: "Default2",    //路由名称
    3                 url: "Ypf",   //路由规则,不区分大小写,当输入“ypf”时,会自动跳转到下面的地址
    4                 defaults: new { controller = "First", action = "Index1", id = UrlParameter.Optional }  //默认值,当Controller或action为空的时候调用
    5             );

    静态路由:url中是一个静态值,访问的URL只有输入这个静态值,才能访问下面default中的默认值。

    测试地址如下:

    http://localhost:7559/                                            【无法访问】

    http://localhost:7559/ypf                                      【 跳转到index1页面】

    http://localhost:7559/First/index1                       【无法访问】

    补充一下:MapRoute方法是可以不需要写参数名的,就像正常的调用方法一样,所以上面的代码可以改写:

    1             routes.MapRoute(
    2                 "Default3",    //路由名称
    3                 "Ypf",   //路由规则,不区分大小写,当输入“Ypf”时,会自动跳转到下面的地址
    4                  new { controller = "First", action = "Index1", id = UrlParameter.Optional }  //默认值,当Controller或action为空的时候调用
    5             );

    3. 组合路由

    1       routes.MapRoute(
    2              "Default4",    //路由名称
    3              "Ypf/{action}",   //路由规则,不区分大小写,规则相符的时候,会自动跳转到下面的地址
    4               new { controller = "First", action = "Index1" }
    5          );

    所谓的组合路由,就是静态路由和动态路由相互组合使用,测试地址如下:

      http://localhost:7559/             【无法访问】       (分析:因为不满足路由规则,没有输入ypf)

      http://localhost:7559/ypf              【 跳转到index1页面】  

      http://localhost:7559/ypf/index1             【 跳转到index1页面】

      http://localhost:7559/Ypf/hh              【404找不到】        (满足路由规则,但是没有hh这个action,所以404)

      http://localhost:7559/ypf/First/index1       【404找不到】        (满足路由规则,但这里把First当做action,并没有这个action,所以404)

    4. 正则约束

    1        routes.MapRoute(
    2                "Default5",
    3                 "{controller}/{action}_{Year}_{Month}_{Day}",
    4                 new { controller = "First", action = "Index1", id = UrlParameter.Optional },
    5                 new { Year = @"^d{4}", Month = @"d{2}", Day = @"d{2}" }
    6             );//正则路由

    所谓的正则约束,是指可以对URL中的参数使用正则表达式进行约束,上述代码约束了Year必须是四位数字,Month和Day必须是两位数字。

    测试地址:

      http://localhost:7559/first/index1_2018_09_01         【跳转到index1页面】

      http://localhost:7559/first/index1         【无法访问】       (分析:因为不满足路由规则,没有输入{Year}_{Month}_{Day} 的参数)

      http://localhost:7559/first/            【无法访问】       (分析:因为不满足路由规则,没有输入{Year}_{Month}_{Day} 的参数

      http://localhost:7559/                【无法访问】        (分析:因为不满足路由规则,没有输入{Year}_{Month}_{Day} 的参数

    5. 命名空间约束

    1         routes.MapRoute(
    2                  name: "Default6",
    3                  url: "{controller}/{action}/{id}",
    4                  defaults: new { controller = "Third", action = "Index", id = UrlParameter.Optional },
    5                  namespaces: new string[] { "Ypf.MVC5" }
    6             );

    所谓的命名空间约束,即限定匹配范围路由的检索范围,提高检索速度。

    特别注意:不能从外层控制器直接跳转到内层Area内的控制器!!

    测试地址:以下三个访问地址,都会跳转到index1页面

      http://localhost:7559/

      http://localhost:7559/First

      http://localhost:7559/First/index1

    6. Area区域内的路由

     1    public override void RegisterArea(AreaRegistrationContext context) 
     2         {
     3             //原路由
     4             //context.MapRoute(
     5             //    "TestOne_default",
     6             //    "TestOne/{controller}/{action}/{id}",
     7             //    new { action = "Index", id = UrlParameter.Optional }
     8             //);
     9 
    10             //结合命名空间进行路由改造
    11             context.MapRoute(
    12                this.AreaName + "_default",
    13                this.AreaName + "/{controller}/{action}/{id}",
    14                new { area = this.AreaName, controller = "Sys_Admin", action = "Index", id = UrlParameter.Optional },
    15                new string[] { "Ypf.MVC5.Areas." + this.AreaName + ".Controllers" }
    16            );
    17 
    18         }

      指MVC5框架中Area区域单独的一套路由规则,我们可以结合区域内的原路由,进行改造一番,如上述代码。

     

  • 相关阅读:
    SourceTree 3.0.17如何跳过注册进行安装? — git图形化工具(一)
    一键复制功能
    如何适配处理iphoneX底部的横条
    .gitignore文件如何编写?
    Spring事务管理——事务的传播行为
    数据库事务之声明式事务
    JVM中的内存分区简介
    SpringMVC中文件的上传(上传到服务器)和下载问题(二)--------下载
    SpringMVC中文件的上传(上传到服务器)和下载问题(一)--------上传
    HashMap和Hashtable的区别
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7885597.html
Copyright © 2020-2023  润新知