• Route@书写规则的总结


    路由书写规则的总结

    概念:Routing System由一组路由组成,每一个路由规则可以匹配一种类型的URL,在请求过来的时候,Ruting ystem 就用它来处理这个URL,路由的任务就是匹配URL,并且将其中的参数值取出来,路由组册的方法在app_Start 的时候就调用了。

     

     

    路由中Segment的概念:

    上面这个URL的路由规则可以是:routes.MapRoute("MyRoute", "{controller}/{action}");

     

    路由匹配的一般规则:                                               

    1、默认情况下我们写的路由的Segment的个数与被匹配的URL的Segment的个数是一致的,否者不会被匹配。

    2、匹配原则: 当我们有多条路由的时候,路由的匹配是有顺序的,一般情况下先定义的路由先进行匹配,成功了以后,后面的路由就不匹配了,如果没有成功就接着匹配后面的路由,因此我们定义路由的时候最好,顺序最好遵循这样的规则:将特殊情况都放在前面定义,范围广德路由放在后面匹配。

    3、路由的默认值比路由的约束条件先执行(这两者后面会讲到)

    4、默认情况下会先在磁盘上找与URL匹配的静态文件,如果找到就不会匹配路由了。

     

    注:如果我们的路由系统只有上面这个一个路由的规则的话,我们运行程序的时候就会报错,因为我们的默认页面请求的URL是没有Segmen的,因此不会被匹配到,这个就涉及到我们后面会讲到的默认值的问题了。

     

     

     

     

     

    路由默认值 :                                                       

    有2个Segments的pattern想要匹配有1个或没有SegmentsURL的时候,可以为pattern加上默认值,如下:

            routes.MapRoute("MyRoute", "{controller}/{action}", new {controller="Home", action="Index"});

    MapRoute的第三个参数就是在设置默认值,这时候就可以将默认页面设置为Home/Index

     

     

    带有静态segment的路由:                                            

    routes.MapRoute("MyRoute", "Hu/{controller}/{action}", new {controller="Home", action="Index"});

    这个pattern中的开头的Hu没有用{}包起来,说明 Hu 是静态的,这样的结果是:

    这个URL必须是以Hu开头的

     

     

    Segment中混有静态部分的路由:                                               

    routes.MapRoute("MyRoute", "Hu{controller}/{action}");

     

     

    带有自定义Segment的路由:                                             

    routes.MapRoute("MyRoute", "{controller}/{action}/{id}",new { controller = "Home", action = "Index",id = "DefaultId" });

    上面这个pattern中有一个自定义的Segment——id,同样,我们也可以为他添加默认值。

     

     

     

    带有可选的Segment变量的路由:                                        

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

    在我们为Segment设置默认值以后我们的URL中没有这个Segment也会被匹配到,但是这时候id还是会被添加一个默认的值,有些人特别注重模块之间解耦,那么我们就可以Segment设置为可选的Segment,这样的话即使URL即使没有该Segment也可以被匹配到,而且不会被设置默认值。

     

     

    可变长度的路由:                                                       

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

    前面3个Segment会分别匹配给controller/action/id,剩下的部分会全部匹配给catchcall,这样就可以匹配任意长度的URL了。

     

     

     

     

    有同名的Controller的解决办法:                                      

    URL匹配成功以后,应用程序会到项目中查找符合名称的Controller,如果找到两个同名的符合条件的Controller就会报错,解决如下:

    routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = "1" }, new[]{"Route_Study.AdditionalControllers"});

    条件:两个同名的controller在不同的目录下,以上处理的实质是在调用 Maproute方法时,再加一个参数,参数是在给方法指定一个命名空间(一个文件夹),制定以后的效果是:

    URL匹配成功后,程序先到指定命名空间中查找controller,查找到以后就不会继续查找了,如果查找不到,就会到其他的命名空间这中查找。

     

    只在制定的文件夹中查找controller:

    有一种情况是:我们只需要在特定的命名空间下查找,即使找不到,我们也不会到其他的命名空间查找,这时的pattern为:

    Route myRoute = routes.MapRoute("AddContollerRoute",                                       //路由名

    "Home/{action}/{id}/{*catchall}",                                                                              //路由规则

    new { controller = "Home", action = "Index",id = UrlParameter.Optional },       //默认值的设置

    new[] { "URLsAndRoutes.AdditionalControllers" });                                                     //设置命名空间

    myRoute.DataTokens["UseNamespaceFallback"] = false;                                             //只在其他命名空间中查找

     

     

     

     

    带有条件约束的路由:

    带有正则表达式约束的路由:                                            

    public static void RegisterRoutes(RouteCollection routes) {

    routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",                                    //路由名、基本路由规则

    new { controller = "Home", action = "Index", id = UrlParameter.Optional },                      //默认值

    new { controller = "^H.*", action = "^Index$|^About$"},                                                                //约束

    new[] { "URLsAndRoutes.Controllers"});                                                                                                        //指定命名空间

    }

    我们首相要知道的是默认值是在约束的前面的执行的,所以当有一个URL"/"过来的话,首先是各个Segment得到默认值,然后是看是否符合约束,

     

     

     

    HTTP 请求的Method属性的限定:                                     

    public static void RegisterRoutes(RouteCollection routes) {

    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") },                                                   //URLMethod进行约束

    new[] { "URLsAndRoutes.Controllers" });

    }

    路由的自定义的约束规则:

     

     

    磁盘文件请求 路由匹配的顺序:                                      

    MVC中,并不是所有的请求都是在请求一个controller中的一个Action

    在默认情况下,当一个请求过来的时候,不会马上将URL与路由进行匹配,而是判断磁盘上是否有与其对应的物理文件,如果有就返回物理文件,而路由就不会用到了,我们通过将routes.RouteExistingFiles属性设置成true,来改变磁盘文件匹配的顺序,如下:

    public static void RegisterRoutes(RouteCollection routes) {

    routes.RouteExistingFiles = true;                                                  //改变顺序

    routes.MapRoute("ChromeRoute", "{*catchall}",

    new { controller = "Home", action = "Index" },

    new {customConstraint = new UserAgentConstraint("Chrome")},

    new[] { "UrlsAndRoutes.AdditionalControllers" });

    要使URL先与路由进行匹配,然后与磁盘上的文件进行匹配,我们还需要对IIS进行配置,具体方法

    请看《pro_asp.net_mvc_4_4th_edition》的P358,电子版在www.it-ebooks.info   上可以下载到

     

     

    在我们将静态文件的匹配放到后面以后,有两种方式来访问静态文件,第一种,为静态文件写路由第二种,用IgnoreRoute方法来访问静态问价

    为磁盘上的文件写路由规则:《pro_asp.net_mvc_4_4th_edition》的P359

    写这种路由要非常小心,因为这个路由是在最后才会被匹配,它很有可能在前面就已经被匹配掉了,因此这个做法不是首选

     

    更好的解决方案是用 IgnoreRoute方法访问静态文件:

    public static void RegisterRoutes(RouteCollection routes) {

    routes.RouteExistingFiles = true;

    routes.IgnoreRoute("Content/{filename}.html");                                             访问静态文件的路由

    routes.MapRoute("DiskFile", "Content/StaticContent.html",

    new {controller = "Customer",action = "List",});

                … ...

    IgnoreRoute的语义是忽略路由,但它的作用并没有很好的体现他的语义,我们可以简单的把他看成是在为静态文件写路由,但是这个路由要放在其他路由的前面,这样就不会被其他的路由覆盖了



  • 相关阅读:
    【Android开发学习笔记】【高级】【随笔】插件化——初探
    【Android测试】【第十三节】Uiautomator——如何组织好你的测试代码(项目实战)
    【Android测试】【第十二节】Uiautomator——API详解
    【Android测试】【第十一节】Uiautomator——简介
    【Android测试】【第十节】MonkeyRunner—— 录制回放
    【Android测试】【第九节】MonkeyRunner—— 初识
    poj 1475 推箱子
    leetcode Ch3-DFS & Backtracking I
    Windows Socket和Linux Socket编程的区别 ZZ
    Linux网络编程入门 (转载)
  • 原文地址:https://www.cnblogs.com/key1309/p/3445349.html
Copyright © 2020-2023  润新知