asp.net mvc3 路由原理


前言

理解asp.net mvc3路由規則很重要。

全局

首先我們來看一副圖片,由於這幅圖是我自己畫的,不是摘自微軟官方,所以如果有什么不到位的地方還望海涵!

 


首先,用戶通過Web瀏覽器向服務器發送一條url請求,這里請求的url不再是xxx.aspx格式,而是http://HostName/ControllerName/ActionName/Parameters的樣子。這個請求被ASP.NET MVC的路由映射系統截獲。(路由映射可以在Global.asax中配置,我們一會再說)路由映射系統按照映射規則,解析出控制器名ControllerName,Action名ActionName和各個參數Parameters,然后,找尋Controllers目錄下的ControllerNameController.cs這個控制器類,默認情況下,系統總是找尋Controllers目錄下的“控制器名+Controller”這么一個類,然后,找尋這個類下與ActionName同名的方法,找到后,將Parameters作為參數傳給這個方法,而后Action方法開始執行,完成后返回相應視圖,默認情況下,會返回Views目錄下與ControllerName同名的目錄下的與ActionName同名的aspx文件,並且將ViewData傳遞到視圖。ViewData中一般包含了控制視圖顯示的控制量以及視圖顯示需要的數據。

我們按以上思路回顧一下上一篇中主頁的請求過程。我們傳遞的url是http://localhost/Home/Index。默認路由規則下,將ControllerName設為“Home”,ActionName設為“Index”,沒有參數。於是系統找尋Controllers目錄下的HomeController類的Index方法,成功找到,於是執行之。這個方法調用Mock的Model取出一些數據,放入ViewData相應鍵值項里。然后返回視圖,返回的是Views下Home下的Index.aspx。這個視圖取出ViewData中的數據按照一定格式呈現,於是完成了一次典型的ASP.NET MVC調用。

路由

從上面可以看出,ASP.NET MVC中路由是很重要的。它直接決定了如何解析url,因此決定了系統如何工作。那么,下面我們來揭開路由神秘的面紗。

打開我們Demo下的Global.asax.cs文件,可以看到如下代碼:

Global.asax.cs:

 

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;
namespace MVCDemo { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults );
} protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } }

 

注意上面有個routes.MapRoute方法。這個方法的作用是向系統增加一條路由規則。這里唯一的一條規則是系統默認增加的,第一個參數是規則名,是一個普通字符串。關鍵是第二個參數,它也是一個字符串,但是它描述了如何解析url。可以這樣理解,它描述了url串HostName后面部分如何匹配,其中帶{}的表示參數匹配,如果不帶則表示字符串匹配。

例如,上面的{controller}/{action}/{id}表示如果HostName后面有三段由“/”分割的字符串,則這個url被匹配,並且分別被解析成控制器名,Action名和一個叫“id”的參數。如果你輸入的是http://localhost/Home/Index/1則后面的“1”將被當做參數id的值,但是如果你請求http://localhost/Home/Index/1/2,抱歉,你的請求無法成功,因為這條路由規則沒法匹配你的url,因為你的HostName后面有四段,而這個路由規則只能匹配三段的。

也許你還注意到一個問題,http://localhost/Home/Index明明HostName后面只有兩段,怎么也被匹配了呢?這就是MapRoute方法的第三個參數起作用了。這個參數的作用是為上面規則中各個{}匹配段設置默認值,如上,id的默認值為"",即空。所以在http://localhost/Home/Index中,雖然沒有顯示指定id,但是它依然可以匹配成功,默認作為空值。如果你把其中id=""去掉,你會發現http://localhost/Home/Index已經無法匹配了。依次類推,http://localhost/Home/也可以匹配成功,因為{action}默認是Index,http://localhost/也可以匹配成功,因為默認{controller}為Home,所以,在這條默認值下http://localhost/Home/Index和http://localhost/是等效的。

綜上分析,我們得出一條重要結論:在默認值被設置的情況下,映射規則“配少不配多”,少的部分由默認值代替。

上面的匹配規則中,三個匹配段都帶大括號的,都是參數匹配,下面我們來說說強字符串匹配。例如,我們有一個url需要這樣http://localhost/Category/Detail/Name。如果按照上面的匹配規則,Name段的值會被匹配到id中去,可是我們想在CategoryController的Detail方法中使用名叫“name”的參數而不是使用名叫“id”的參數,怎么辦呢?很簡單,我們增加一下一條匹配規則:

 

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;
namespace MVCDemo { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Category", // Route name "Category/Detail/{name}", // URL with parameters new { controller = "Category", action = "Detail", name = "" } // Parameter defaults ); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } }

 

可以看到,我們在默認規則前增加了一條規則,其中其中控制器名和Action名不再是參數,而變成了強字符串(沒有{})。這時,當我們請求的url是http://localhost/Cateogry/Detail/para的形式時,就會直接匹配新加的規則,而para的值不會被賦給成id而是賦給名叫name的變量。

需要注意的是,我們新的路由規則一定要放在前面,因為ASP.NET MVC會自上向下匹配第一條找到的可匹配路由規則。

視圖

說完了路由規則,我們再來說說視圖。

上面說道,Action方法返回類型是ActionResult,其實這個返回類型不局限於View方法返回ViewResult,它還有很多實現,這里列舉幾個。

ViewResult:一般呈現某個aspx文件,由View方法返回。

RedirectToResult:使瀏覽器重定向,由Redirect方法返回。

RedirectToRouteResult:直接交給下一個Action,由RedirectToAction方法返回。

 


免責聲明!

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



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