MVC筆記 網址路由與MVC的生命週期

來源:互聯網
上載者:User

標籤:

一、網址路由

      1.1  比對通過瀏覽器傳來的HTTP請求

         用戶端對ASP.NET網站發出請求時,能通過R偶湯尼蓋找到適當的HttpHandler來處理網頁,大致的流程

         如果HttpHandler是由MvcHandler來處理,那麼,此時就會進入MVC的執行生命週期,並且會找到適當的Controller與Action來對其進行處理,並將資訊反饋給用戶端。

      1.2 將適當的網址返回瀏覽器

        網址路由的另一個用途是決定MVC 應該輸出什麼樣的網址並將其返回瀏覽器,跳轉地址或在View中顯示超連結時,都需要參考網址路由的定義,因為這樣才能動態決定MVC輸出網址應該是什麼。

     1.3  預設網址路由

        Global.asax已經定義了兩個預設的網址路由,參考圖如下:

      ① 所有ASP.NET Web應用程式執行的入口都是HttpApplication的Application_Start()事件,所有的MVC Routing都會在此定義。其中,RoutTable.Routes是一個公開的靜態對象,用於儲存所有Routing的規則集(RouteCollection類)。

      ② 預設RegisterRoutes()方法中的IgnoreRoute()輔助方法用於定義不需要通過Routing處理的網址。

      ③ "{resource}"代表一個名為"resource"的Route Valueg運算式,但其實這裡取任何名字都可以,它只是代表一個變數空間(PlaceHolder類),總之就是代表一個位置,用於放置一個用不到的變數。

       "{*pathInfo}"代表一個名稱為"pathInfo"的RouteValue運算式,名稱前面的星號(*)的意思是"CatchAll"(抓到全部)。這個名為"pathInfo"的RouteValue運算式的值是完整的路徑資訊(Path Info)中扣除在中比對到的剩餘的網址。例如:網址是"/TEST.axd/a/b/c/d",則"{PathInfo}"的值為"a/b/c/d",如果沒有加上星號,"{PathInfo}"的值應為"a"。其實在這裡取任何名字都可以,因為它只代表一個變數的位置。

     ⑤ MapRoute()是最常用來定義Routing規則的輔助方法。

      定義Route的名稱,在此為"Default"。

      定義網址格式和每個網址段落(PathSegment)的RouteValue運算式名稱。

TIP : 該網址不能以斜線(/)開頭。

      定義各RouteValue運算式的預設值,當網址路由比對不到HTTP請求網址時,就會改以預設值替代。

二、HTTP請求的URL如何對應網址路由

      由於預設定義了兩個網址路由,按照ASP.NET Routing的規則,當HTTP提出請求後,URL會進行網址路由的比對,而且是由上而下地一條一條比對,直到比對到符合HTTP請求的網址為止。

   2.1 網址路由範例

      下面舉例,弄清URL和Routing之間更多概念上的聯絡。

     [1]. http://localhost/Trace.axd/a/b/c/d/e
TIP :所有的網址都是從"http://localhost/"之後開始比對的!

  • 比對順序

    (1)比對routes.IgnoreRoute命名空間的"{resource}.axd/{*pathInfo}"網址格式。

    (2)"{resource}.axd"比對到"Trace.axd",因此繼續比對下一個RouteValue運算式。

    (3)比對"{*pathInfo}",得到"a/b/c/d/e"。

    (4)因為所有的RouteValue運算式都比對成功,所以該HTTP請求會由此網址路由提供服務。

  • 比對結果

     該網址使用routes.IgnoreRoute命名空間進行處理,即,MVC為忽略此請求,改為ASP.NET架構本身繼續進行處理。

    [2] http://localhost/Trade.axd

  •  比對順序

    (1)比對routes.IgnoreRoute命名空間的"{resource}.axd/{*pathInfo}"網址格式。

    (2)"{resource}.axd"比對到"Trace.axd",因此繼續比對下一個RouteValue運算式。

    (3)比對"{*pathInfo}",由於請求的部分已經沒有資料,所以理論上不會比對到任何結果。但由於"{*pathInfo}"屬於CallAll,此文法會比對到包括Null 字元串在內的全部內容,所以這個部分也算比對成功,只是"{*pathInfo}"為空白而已。

   (4)因為所有的RouteValue運算式都比對成功,所以該HTTP請求會由此網址路由提供服務。

  • 比對結果

     該網址使用routes.IgnoreRoute命名空間進行處理,即,MVC為忽略此請求,改為ASP.NET架構本身繼續進行處理。

     [3] http://localhost/Member/Detail?id=123

  • 比對順序

    (1)比對routes.IgnoreRoute命名空間的"{resource}.axd/{*pathInfo}"網址格式。

    (2)比對請求URL的的一部分,即"Member",由於沒有比對到".axd",所以比對失敗。

    (3)跳轉到routes.MapRoute命名空間的"{controller}/{action}/{id}"網址格式。

    (4)比對請求URL的第一部分,即"Member",並且比對到{controller}參數。

    (5)比對請求URL的第二部分,即"Detail",並且比對到"{action}"參數。

    (6)接下來的"?id=123"就不算是網址的一部分了,所以它不會被算進RouteValue運算式中,因此不會在對此比對了。

    (7)"{id}"部分因為沒有比對到,所以會讀取預設值,也就是"UrlParameter.Optional"部分。由於存在預設值,所以也算比對成功。

    (8)因為所有的RouteValue運算式都比對成功,所以該HTTP請求會由此網址路由提供服務。

  • 比對結果

     該網址使用routes.MapRoute命名空間進行處理,並調過MvcHandler將值賦予適當的Controller和Action程式。在這裡會對應MemberController的Detail動作。

TIP :在"URL及參數"位置出現的所有路由參數都是必要的參數,必須完全符合必讀規則才能比對成功;如果比對失敗,就會調至下一條網址路由規則繼續比對。

   2.2 為網址路由加上限制條件

     MapRoute()是最常用來定義Routing規則的輔助方法,它有許多應用方式(重載)。一個常用的應用方式為"樣式比對規則(Regex)+限制條件"。

1            context.MapRoute(2 3                  "Order_default",4                  "Order/{controller}/{action}/{id}",5                  new { action = "Index", id = UrlParameter.Optional },6                  new { id = @"\d+" }7             );

      我們在MapRoute()輔助方法中設定了4個參數,這些參數指定了一個匿名對象,其中的id屬性就是我們比對{id}路由值的限制條件,其限制條件是用Regex(Regular Expression)來表示的。"\id+"代表比對到的{id}路由值時必須為數字才算比對成功,而這就是限制條件。

      若網址為"http://localhost/Order/Member/Index/123ABC.",由於此對到的{id}路由值不符合限制條件,所以這個網址就算比對失敗,接著會自動跳到下一個網址路由規則繼續比對。

TIP : 這裡定義的Regex預設是完全比對。如果你定義的樣式為"\id+‘,事實上,在比對時會轉換為"^\d+$"。

三、網址路由如何在MVC中產生網址。

      URL是如何比對網址路由是網址路由的一個功能,另一個主要功能是在Controller或View中依據網址路由的定義產生適當的網址。下面介紹如何使用RouteTable.Routes.GetVirtualPath命名空間取得動態網址。

     先用預設的MVC項目模組進行測試。開啟網址http://localhost/Home/About,此請求所得到的路由值

欄位

controller

Home

action

About

id

UrlParameter.Optional

    在"/Views/Home/About.aspx"頁面中添加以下程式碼。

1        <%=2             RouteTable.Routes.GetVirtualPath(3                  Request.RequestContext,4                  new RouteValueDictionary(new { page=1})5             ).VirtualPath        6         %>

     可以看到:在RouteTable.Routes.GetVirtualPath命名空間中,第一個參數為Request.RequestContext,在會輸入當前的請求資訊,包括RouteValue、QueryString和其他完整的請求;第二個參數中多輸入了一個RouteValueDictionary對象,並插入了一個{page}路由值。因此,在擷取網址路由之前會先合并出一組路由值,如表所示:

欄位

Action

About

Id

UrlParameter.Optional

Page

1

      最後,MVC會使用這組新的路由值由上而下——比對路由表(RouteTable)中所有的路由規則,已得到最適合的路由規則,併產生適當的網址。

      拿以下路由規則來說,其中定義了3個路由參數,而我們得到的4個路由值中有3個路由值完全符合定義,所以,此網址路由會被選中,並且MVC會以此路由定義好的格式產生網址。

 1           routes.MapRoute( 2                 "Default",                     // 路由名稱 3                 "{controller}/{action}/{id}",  // 帶有參數的 URL 4                 new 5                 {                              // 參數預設值  6                     controller = "Home", 7                     action = "Index", 8                     id = UrlParameter.Optional 9                 }10             );

      由於{page}參數並非網址路由參數之一,因此,建立的{page}參數就被替換成了QueryString參數,輸出結果如下。

            /Home/About?page=1

      再舉一個複雜的例子。第一條路由規則定義如下:

 1           routes.MapRoute( 2                 "Member",                       // 路由名稱 3                 "Member/{action}/{page}",       // 帶有參數的 URL 4                 new                             // 參數預設值  5                 { 6                     controller = "MemberCenter", 7                     action = "List" 8                 }, 9                 new10                 {11                     action = @"Index|List|Detail",12                     page = @"\d+"13                 }14             );15             routes.MapRoute(16                 "Default",                     // 路由名稱17                 "{controller}/{action}/{id}",  // 帶有參數的 URL18                 new19                 {                              // 參數預設值 20                     controller = "Home",21                     action = "Index",22                     id = UrlParameter.Optional23                 }24             );

     在"/Views/Home/About.aspx‘頁面中添加以下程式碼。

 1         <%= 2             RouteTable.Routes.GetVirtualPath( 3                   Request.RequestContext, 4                           new RouteValueDictionary(new {  5                              controller ="MemberCenter", 6                              action="Detail" 7                           }) 8             ).VirtualPath 9             10         %>

      在第2個參數中將"controller"替換成"MemberCenter",將"action"替換成"Detail",所以在獲得網址之前,會先合并出一組新的路由值,如表:

欄位

controller

MemberCenter

action

Detail

id

UrlParameter.Optional

     MVC會用這組新的路由值由上而下一一比對路由表中的所有路由規則,以得到最適合的路由規則。當此對比到第一個規則時,由於已經定義了兩個路由參數,分別是"{action}"和"{page}",而我們的路由表中只有"action"沒有"page",此時就會查看參數預設值中是否有預設的{page}參數,結果還是沒有,因此比對失敗。MVC並不會以這個網址路由來產生網址,進而跳至下一條網址路由進行比對。最後,比對的結果為"/MemberCenter/Detail"。

     修改"/Views/Home/About.aspx‘頁面的程式碼,增加"page"參數,樣本如下:

 1        <%= 2             RouteTable.Routes.GetVirtualPath( 3                   Request.RequestContext, 4                           new RouteValueDictionary(new {  5                              controller ="MemberCenter", 6                              action = "Detail", 7                              page = "TEST" 8                           }) 9             ).VirtualPath10             11         %>

     執行以上操作後就會合并出一組新的路由值(RouteValue),如表:

欄位

controller

MemberCenter

action

Detail

id

UrlParameter.Optional

page

TEST

     當我們比對第一條規則時,由於已經定義了兩個路由參數,分別是{action}和{page},而我們的路由表中已有"action"和"page"的路由值了,必要參數已經全部符合,所以會進一步比對限制條件是否符合。

     由於已經定義了{page}參數的限制條件為“@"\d+"”,但路由值中的page值卻是"TEST",因限制條件無法通過,所以比對還是失敗了。因此,MVC並不會用這個網址路由來產生網址,進而跳至下一個網址路由進行比對。

     最後比對結果為"/MemberCenter/Detail?page=TEST"。

     總結:使用RouteTable.Routes.GetVirtualPath命名空間來產生網址大致會用到以下判斷依據。

  • 若將第1個參數帶入Request.RequestContext命名空間,會預先取得當前所有的路由值。也可以輸入"null"代表沒有預設的路由值。
  • 用當前合并後的所有路由值與網址路由表一一比對所有規則時,會先比對所有必要參數。若比對成功,就會進一步檢查限制條件是否符合。
  • 若找不到必要參數,就會尋找參數預設值;如果仍然找不到,則比對失敗。
  • 若上述比對全部成功,RouteTable.Routes.GetVirtualPath命名空間就會用該網址路由定義的網址來產生網址。

     RouteTable.Routes.GetVirtualPath命名空間產生網址的完整流程圖。

四、MVC執行的生命週期

      MVC的執行生命週期大致上分成3階段,分別是:

     (1)網址路由比對;

     (2)執行Controller與Action;

     (3)執行View並返回結果。

      4.1 網址路由比對

      當IIS收到HTTP請求後,會先通過UrlRoutingModule處理所有與網址路由有關的運算。預設下若網址可以對應到網址根目錄下的實體檔案,就不會通過MVC進行處理,而是直接交由IIS或ASP.NET執行。

      若網址是"http://localhostContent/Site.css",由於在網站根目錄下有"Content"目錄,而且"Content"目錄中也有Site.css檔案,所有MVC不會將此網址解析成Content控制器和Site.css動作。

      再舉一個.NET Web Forms的例子,網址為"http://localhost/Member/Login.aspx",在Global.asax檔案中建立一個特殊的網址路由,具體如下。

 1           routes.MapRoute( 2                 "Default_aspx",                     // 路由名稱 3                 "{controller}/{action.aspx}/{id}",  // 帶有參數的 URL 4                 new 5                 {                                   // 參數預設值  6                     controller = "Home", 7                     action = "Index", 8                     id = UrlParameter.Optional 9                 }10             );

      在這種情況下,若在網站根目錄中有使用.NET Web Forms編寫的"/Member/Login.aspx"程式存在,MVC就不會應用UrlRouting,而是將流程的控制權交給IIS,並由IIS將其交友下一個模組執行。在此,就會執行"/Member/Login.aspx"程式。

      如果"/Member/Login.aspx"程式不存在,那麼MVC的Routing就會正式啟動比對,並且在比對到上述網址後,將執行MemberController的Login動作。

      若果在Global.asax檔案的Application_Start()事件的最前面將RouteTableRoutes.RouteExistingFiles參數值設定為"true",MVC的UrlRouting就不會先判斷是否有實體檔案存在,程式碼如下:

1        protected void Application_Start()2         {3             RouteTable.Routes.RouteExistingFiles = true;4             AreaRegistration.RegisterAllAreas();5 6             RegisterRoutes(RouteTable.Routes);7         }

    設定完後,該網站收到的所以HTTP請求都會使用RegisterRoutes()方法中定義的網址路由規則一一進行比對。若比對成功,會用MVC進行處理;否則,將執行的權利交還給IIS。

NOTE : 若在MVC中是由IgnoreRoute()輔助方法比對成功的,會導致程式直接跳離MVC執行生命週期,將程式繼續執行的權利交還給IIS,由IIS覺得接下來該由哪個模組(Model)或哪個處理曆程(Handler)來執行。

     在使用RegisterRoutes()方法定義的網址路由規則進行比對時,事實上,比對成功後,預設值會由MvcRouteHandler決定要將改HTTP請求發送給哪個HttpHandler來執行,。MVC預設會將HTTP請求交給MvcHandler來執行。

    由圖所示的MvcRouteHandler程式碼可知,若要自訂RouteHandler,只要自行開發IRouteHandler介面的類,即可通過自訂的RouteHandler來決定通過網址路由比對的網址應該交給哪個HttpHandker來執行。所以,可以通過自訂RouteHandler和HttpHandler來為MVC網站提供協助工具功能。

    4.2 執行Controller和Action 4.3 執行View並返回結果

     當程式執行到MvcHandler時,HttpHandler的入口是ProcessRequest()方法。

MVC筆記 網址路由與MVC的生命週期

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.