ASP.NET MVC Route詳解


Routing深入詳解

  首先,ASP.Net MVC項目是URL請求驅動的,為什么訪問localhost/home/index會傳遞給HomeController中名為index的action(即HomeController類中的index方法)?

下面,我們一一來看下。

1.1 Routing的作用

  假如有一個請求:localhost/home/index,那么路由需要做的事情如下:

  (1)確定Controller

    (2)確定Action

  (3)確定其他參數

  (4)根據識別出來的數據,將請求傳遞給Controller和Action

1.2 神奇的路由規則

  根據路由的作用,我們可以知道它是一個“指路人”,指示我們的請求應該到達哪個Controller中的Action。那么,它是根據什么規則來指路的呢?我們可以在App_Start文件夾中的RouteConfig類中找到這個神奇的規則是如何制定的。

復制代碼
public static void RegisterRoutes(RouteCollection routes)
{
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      routes.MapRoute(
          name: "Default",
          url: "{controller}/{action}/{id}",
          defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
      );
}
復制代碼

  (1)首先,第一句routes.IgnoreRoute代表對所有axd的資源訪問請求進行忽略,直接進行URL訪問;這里可以閱讀參考資料第(5)篇,了解其詳細含義,這里就不再贅述;

  (2)然后,第二句開始使用MapRoute方法對整個網站定義了一個路由識別規則,這個規則的name是Default,url規則為:{controller}/{action}/{id}。例如我們要訪問的URL為:localhost/home/index,在這個URL中,localhost是域名, 所以首先要去掉域名部分: home/index,也是就對應了上面代碼中的這種URL結構: {controller}/{action}/{id}。正是因為我們建立了這種URL結構的識別規則,,所以能夠識別出 Controller是home, action是index, id沒有則為默認值""。

  (3)在MapRoute方法中為所有URL請求定義了一個defaults默認值:controller為空則指向Home,action為空則指向Index,而id則是可選的,非必須要的。

  這里,對於路由規則需要注意的有兩點:

  (1)可以有多條路由規則;

  (2)路由規則是有順序的(前面的規則被匹配后,后面的規則就不再匹配);

  我們可以在RegisterRoutes這個方法中添加一條自定義路由規則,並取名為Default2,具體規則代碼如下:

routes.MapRoute(
     name: "Default2",
     url: "{controller}-{action}-{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

  這下如果我們以:localhost/Home-Index來訪問時,我們原本想要的是根據Default2這個路由規則訪問Home控制器下的Index這個Action,但卻被告知以404提示:

  這是為什么呢?我們再來看看RegisterRoutes這個方法:

復制代碼
public static void RegisterRoutes(RouteCollection routes)
{
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            routes.MapRoute(
                name: "Default2",
                url: "{controller}-{action}-{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
}
復制代碼

  我們剛剛提到,路由規則是有順序的(前面的規則被匹配后,后面的規則就不再匹配)。那么,可以推斷,由於Default2在Default之后,有可能我們的請求localhost/Home-Index已經被Default這個規則所匹配了,因此Default2規則根本沒有出場Show一下。那么,在Default規則中,它將Home-Index作為Controller的名字匹配,去訪問Home-Index這個Controller,而Action使用默認的Index,那么它所請求的應該是這個URL:/localhost/Home-Index/Index。由於網站中,並沒有Home-Index這個Controller,所以也就出現了剛剛那個404頁面。

1.3 MapRoute方法介紹

  (1)MapRoute方法提供了以下幾種方式的重載

  MapRoute( string name, string url);
  MapRoute( string name, string url, object defaults);
  MapRoute( string name, string url, string[] namespaces);
  MapRoute( string name, string url, object defaults, object constraints); MapRoute( string name, string url, object defaults, string[] namespaces);
  MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);

  我們在上面所使用的便是第二種重載。

  (2)MapRoute方法參數詳細介紹:

  ①name參數:

  規則名稱, 可以隨意起名。不可以重名,否則會發生錯誤: “路由集合中已經存在名為“Default”的路由。路由名必須是唯一的”。

  ②url參數:

  url獲取數據的規則,這里不是正則表達式,將要識別的參數括起來即可,比如: {controller}/{action}

  最少只需要傳遞name和url參數就可以建立一條Routing(路由)規則,比如實例中的規則完全可以改為:

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

  ③ defaults參數:
  url參數的默認值:如果一個url只有controller: localhost/home/,而且我們只建立了一條url獲取數據規則: {controller}/{action},那么這時就會為action參數設置defaults參數中規定的默認值。由於defaults參數是Object類型,所以可以傳遞一個匿名類型來初始化默認值:new { controller = "Home", action = "Index" }。
  在ASP.Net MVC網站默認實例中使用的是三個參數的MapRoute方法:
routes.MapRoute(
     name: "Default",
     url: "{controller}/{action}/{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
  ④ constraints參數: 
  用來限定每個參數的規則或Http請求的類型。constraints屬性是一個RouteValueDictionary對象,也就是一個字典表,但是這個字典表的值可以有兩種類型:
  一是:用於定義 正則表達式的字符串(正則表達式不區分大小寫)。通過使用正則表達式可以規定參數格式,比如controller參數只能為4位數字:new { controller = @"\d{4}"}
復制代碼
routes.MapRoute(
     name: "Default2",
     url: "{controller}-{action}-{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
     constraints: new { controller = @"\d{4}" }
);
復制代碼
 
  二是:一個用於實現 IRouteConstraint 接口且包含Match方法的對象。

  例如:通過第IRouteConstraint 接口可以限制請求的類型(是GET還是POST)。因為System.Web.Routing中提供了HttpMethodConstraint類,,這個類實現了IRouteConstraint 接口。

  我們可以通過為RouteValueDictionary字典對象添加鍵為"httpMethod", 值為一個HttpMethodConstraint對象來為路由規則添加HTTP 謂詞的限制,比如限制一條路由規則只能處理GET請求:httpMethod = new HttpMethodConstraint( "GET" )

復制代碼
routes.MapRoute(
     name: "Default2",
     url: "{controller}-{action}-{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
     constraints: new { 
           controller = @"\d{4}", 
           httpMethod = new HttpMethodConstraint("GET") }
);
復制代碼

1.4 URL路由實例詳解

  一般來說,對於一個網站為了SEO友好,網址的URL層次最好不要超過三層:localhost/{頻道}/{具體網頁},其中域名第一層, 頻道第二層, 那么最后的網頁就只剩下最后一層了。如果使用默認實例中的“{controller}/{action}/{其他參數}"的形式則會影響網站的SEO。

  假設我們有一個綜合型服務網站,其中有租房頻道、酒店頻道、KTV頻道、電影院頻道等等。我們應該怎樣來設計URL路由規則呢?

  (1)首先,我們知道:可以有多條路由規則,但是路由規則是有順序的(前面的規則被匹配后,后面的規則就不再匹配);所以,我們可以定義多條路由規則,粒度細的模塊(比如:具體的酒店列表頁面)路由規則放最前面,粒度粗的模塊(比如:門戶網站的首頁)路由規則放在最后面。

  (2)其次,根據模塊粒度划分層次結構,以粒度粗細排序為:網站首頁->頻道首頁->具體內容;

  (3)最后,我們可以看一個具體的URL路由實例來分析一下:

復制代碼
// 酒店列表頁匹配
routes.MapRoute(
     "酒店列表頁",
     "hotels/{action}-{city}-{price}-{star}",
     new { controller = "Hotel", action = "list", city = "beijing", price = "-1,-1", star = "-1" },
     new { city = @"[a-zA-Z]*", price = @"(\d)+\,(\d)+", star = "[-1-5]" }
);

// 酒店頻道所有匹配 
routes.MapRoute(
     "酒店首頁",
     "hotels/{*iiii}",
     new { controller = "Hotel", action = "default", hotelid = "" }
);
            
// 網站首頁默認匹配
routes.MapRoute(
     "網站首頁",
     "{*values}",
     new { controller = "Home", action = "index" }
);
復制代碼

  (4)我們可以分析一下上面的路由規則所實現的功能:

   ①訪問 www.mywebsite.com/hotels/list-chengdu-100,200-3 會訪問酒店頻道的列表頁,並傳入查詢參數(price為100,200,star為3);

   ②訪問 www.mywebsite.com/hotels 下面的任何其他頁面地址,都會跳轉到酒店首頁;

   ③訪問 www.mywebsite.com 下面的任何地址,如果未匹配上面2條,則跳轉到首頁;

  (5)根據上面的規則和實現的功能,我們可以做一個簡單的總結如下:

   ①Routing規則有順序(按照添加是的順序),如果一個url匹配了多個路由規則,則按照第一個匹配的路由規則執行

   ②由於上面的規則,要將具體頻道的具體頁面放在最上方,將頻道首頁 和 網站首頁 放在最下方。

   ③{*values}表示后面可以使用任意的格式。

1.5 URL路由調試

  在ASP.Net MVC中,默認是不允許對路由規則進行調試的。但是,我們可以通過使用RouteDebug來輔助進行調試。

  (1)首先,我們下載RouteDebug.dllMvcContrib.dll到我們的項目中,並添加對其的引用。

  (2)其次,在Global.asax中的Application_Start方法中添加一句代碼:

  RouteDeug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes); 

復制代碼
protected void Application_Start()
{
     AreaRegistration.RegisterAllAreas();

     WebApiConfig.Register(GlobalConfiguration.Configuration);
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
     RouteConfig.RegisterRoutes(RouteTable.Routes);
     BundleConfig.RegisterBundles(BundleTable.Bundles);
     RouteDeug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}
復制代碼

  (3)最后,F5調試運行,我們請求localhost/Home-Index這個URL時,可以清楚地發現,系統將Home-Index匹配了第一條默認路由規則,也就是將Home-Index作為Controller的名稱進行匹配,這也就證明了為什么我們輸入這個請求不會匹配第二條Default2的路由規則出現剛剛那個404頁面了。

 

 

 


免責聲明!

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



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