一. 什麼是路由html
路由是約束URL的一組規範,那麼什麼是URL呢?通俗的來講URL是一個地址,經過該地址,用戶能夠訪問Web網站或者下載服務器上的文件。正則表達式
好比下面就是兩組URL:服務器
http://www.cnblogs.com/yaopengfei/p/7828441.html框架
http://www.cnblogs.com/yaopengfei/p/7828441ide
顯然咱們喜歡第二組,省略.html,會使該地址看起來更加簡潔,更加友好,利於SEO優化。測試
那麼咱們怎麼實現這個簡單的需求呢?優化
答案是:經過【路由】配置,因此如今咱們彷佛有點清晰了,路由能夠規定URL的特殊格式,使其達到特殊效果。網站
在ASP.NET MVC框架中,經過路由配置URL,使用戶的URL請求能夠映射到Controller下的action方法中,執行相應操做,並接受URL中傳過來的參數,在MVC5框架中,在【RouteConfig.cs】類中進行路由規則的配置,以下圖:this
二. 從源碼的角度分析路由url
咱們進入【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區域單獨的一套路由規則,咱們能夠結合區域內的原路由,進行改造一番,如上述代碼。