第二節:各種路由約束(動態路由、靜態路由、組合路由、正則約束、命名空間約束、區域內路由)


一. 什么是路由

   路由是約束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區域單獨的一套路由規則,我們可以結合區域內的原路由,進行改造一番,如上述代碼。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM