概述
在傳統的ASP.NET應用程式中,發生一個請求之後將映射到一個.aspx檔案,且會對應到一個具體的物理aspx檔案。ASP.NET MVC Framework中,進入一個請求之後,不再是映射到.aspx檔案,而是由MVC Framework中提供的直接選取引擎,映射到正確的Controller和Action執行請求。ASP.NET MVC Framework中URL路徑映射規則定義在Global.asax中,這在一定程式上帶來了很多的靈活性,如果想要修改URL應用結構的話,只需要修改一下映射規則即可,並不需要修改Controller和View中的代碼,但是這仍然不夠靈活。改變Global.asax代碼仍然會導致應用程式的重新編譯,本篇文章末尾部分將會介紹如何通過HttpModule定義映射規則在Web.config中。
理解直接選取
先看一下下面這幅圖:
從中可以看到,發生一個請求之後,第一步就是直接選取,而映射規則是通過在Routes集合中添加Route執行個體來註冊的,如:
RouteTable.Routes.Add( new Route { Url = "[controller]/[action]", Defaults = new { action = "Index"}, RouteHandler = typeof(MvcRouteHandler) });
Route中有四個屬性,它的定義如下:
public class Route{ public Route(); public Route(string url, Type routeHandler); public Route(string url, object defaults, Type routeHandler); public object Defaults { get; set; } public Type RouteHandler { get; set; } public string Url { get; set; } public object Validation { get; set; }}
其中:
Url指定了請求的Url匹配規則,還定義了URL應該如何分割成(tokenized)不同的參數,URL中可替換的參數,是通過 [參數名稱] 的句法來定義的。
Defaults屬性定義了一個預設值的字典,可以在進來的URL並不包含某個指定的參數值的情形下使用。
RouteHandler屬性定義了在URL被分割成參數,適當的直接選取規則被確定之後,應該用來處理請求的 IRouteHandler 執行個體。
Validation屬性允許我們指定一個直接選取規則匹配需要滿足的先決條件,如對參數值使用Regex,來過濾一個直接選取規則是否匹配。
II6與II7的區別
在使用ASP.NET MVC Framework時,要注意一點II6和II7的區別,如果在II7下,不需要使用.mvc副檔名,直接選取規則可以如下所示:
RouteTable.Routes.Add( new Route { Url = "[controller]/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(MvcRouteHandler) });
而在II6下,控制器名後面必須要有.mvc副檔名:
RouteTable.Routes.Add( new Route { Url = "[controller].mvc/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(MvcRouteHandler) });
直接選取規則的驗證
在本文第二節我們提到過Route的一個Validation屬性,允許我們指定一個直接選取規則匹配需要滿足的先決條件。如下程式碼片段所示,驗證Id必須為整數且長度在1到8之間:
RouteTable.Routes.Add( new Route { Url = "Blog.mvc/Detail/[id]", Defaults = new { controller = "Blog", action = "Detail" }, Validation = new { id=@"\d{1,8}" }, RouteHandler = typeof(MvcRouteHandler) });
自訂RouteHandler
在ASP.NET MVC Framework中,提供了很好的擴充功能,如我們可以自訂RouteHandler來實現在Web.config中配置ControllerFactory和ViewFactory。在ASP.NET MVC Framework中,自訂RouteHandler只需要實現IRouteHandler介面並實現GetHttpHandler方法,它的定義如下:
public interface IRouteHandler{ IHttpHandler GetHttpHandler(RequestContext requestContext);}
Fredrik在它的Blog上寫了一個完整的樣本,有興趣的朋友可以參考一下。
在Web.config中定義直接選取規則
ASP.NET MVC Framework中直接選取規則定義在Global.asax中的Application_Start方法中,當映射規則發生改變時,如果修改了Application_Start中的代碼,必將導致整個應用程式的重新編譯,我們完全可以通過HttpModule來實現把映射規則放在設定檔中。如下範例程式碼所示:
public class RouteBuilder : IHttpModule{ public void Init(HttpApplication application) { RouteConfiguration routeConfig = (RouteConfiguration)System.Configuration.ConfigurationManager.GetSection("RouteTable"); foreach (RouteElement routeElement in routeConfig.Routes) { Route currentRoute = new Route(); currentRoute.Defaults = new DefaultsType(routeElement.Defaults); currentRoute.Url = routeElement.Url; currentRoute.RouteHandler = typeof(MvcRouteHandler); RouteTable.Routes.Add(currentRoute); } } public void Dispose() { }}
在CodePlex上,已經有了做了這樣的開源項目,地址為:http://www.codeplex.com/RouteBuilder,有興趣的朋友參考一下。
結束語
關於ASP.NET MVC Framework中的直接選取就簡單的介紹到這兒了,其實本篇文章後兩節都是在推薦一些學習的資料,而關於直接選取的詳細內容,在ScottGu的文章裡已經寫的很仔細了。
最後,再次做個小廣告:我在部落格園社區中建立了一個Web技術聯盟小組,歡迎大家加入。同時,該小組將在近期會有一些活動,來提高社區的氛圍:)