ASP.NET MVC路徑選擇系統構建
從路徑選擇系統構建輸出的URL
在本文的前面,我說過ASP.NET MVC路徑選擇系統負責兩件事情:
把進來的URL映射到處理的Controllers/Actions上
幫著構建可以在以后用來回調Controllers/Actions的輸出到客戶端的URL(例如,表單提交, < a href="">鏈接, 和 AJAX 調用等等)
URL路徑選擇系統有不少輔助方法和類,方便你在運行時動態查看和構建URL(你也可以直接對RouteTable的Route集合進行操作來查看URL)。
Html.ActionLink
在本博客系列的第一部分,我簡單地討論了Html.ActionLink()視圖輔助方法。它可以在視圖里使用,允許你動態地生成 < a href=""> 超鏈接。比較酷的是,它可以使用MVC路徑選擇系統里定義的URL映射規則來生成這些URL。例如,下面2個Html.ActionLink 調用:
automatically pick up the special Search results route rule we configured earlier in this post, and the "href" attribute they generate automatically reflect this: 會自動地使用我們在本貼子前面配置的的特殊查詢結果路徑規則,它們自動生成的href屬性反映了這個情況:
特別地,注意上面,Html.ActionLink的第二個調用自動地把page參數映射成URL的一部分(也注意,第一個調用省略了page參數值,因為它知道服務器端會自動提供默認值)。
ASP.NET MVC路徑:Url.Action
除了使用Html.ActionLink外,asp.net mvc還有個Url.Action()視圖輔助方法。該方法生成原生的字符串URL,然后你可以任何方式來使用它們。例如,下面的代碼片段:
會使用URL路徑選擇系統返回下面這個原生的URL(而不是包裝在 < a href=""> 元素里):
ASP.NET MVC路徑:Controller.RedirectToAction
asp.net mvc還提供了Controller.RedirectToAction()輔助方法,你可以在控制器里使用來進行轉向操作(URL是使用URL路徑選擇系統計算出來的)。
例如,當在控制器里調用下面代碼時:
在內部,它會生成一個對Response.Redirect("/Search/Beverages")的調用。
DRY (別重復自己)
上述所有的輔助方法的好處在于它們允許我們避免在我們的控制器和視圖邏輯中硬寫URL。如果在后來我們決定改變查詢URL路徑映射規則,從"/Search/[query]/[page]" 改回到 "/Search/Results/[query]/[page]" 或者 "/Search/Results?query=[query]&page=[page]" ,我們只要在一個地方(我們的路徑注冊代碼中)做編輯,就可以輕松搞定。我們不需要改動視圖或控制器中的任何代碼,就可以撿起新的URL(這就堅持了“DRY原則”)。
使用Lambda表達式從路徑選擇系統構建輸出的URL
前面的URL輔助方法例子使用了VS 2008中VB和C#現在支持的新的匿名類型。在上面的例子中,我們使用了匿名類型來有效地傳入一串名稱/數值對,用以幫助映射URL(你可以把這想像為生成字典的一個比較干凈的方式)。
除了使用匿名類型以動態方式傳遞參數外, asp.net mvc框架還支持使用強類型機制創建action路徑的能力,這些強類型機制為URL輔助方法提供了編譯時檢查和intellisense。這是通過使用泛型和新的VB和C#對Lambda表達式的支持來實現的。
例如,下面這個匿名類型 ActionLink 調用:
也可以寫成:
除了寫起來簡短外,這第二個選項還有類型安全的好處,這意味著你得到對表達式的編譯時檢查以及Visual Studio的代碼intellisense(你還可以使用重構工具對它進行重構):
注意上面,我們是如何使用intellisense挑選出我們想用的SearchController的Action方法的,以及參數是強類型的。生成的URL都是由asp.net mvc url路經選擇系統驅動的。
你也許在想,這到底是怎么回事呢?如果你還記得,8個月前,我在博客里討論Lambda表達式時,我談到了Lambda表達式既可以編譯出成代碼代理(delegate),也可以編譯成表達式樹對象,然后在運行時可以用來分析Lambda表達式。對于Html.ActionLink< T> 輔助方法,我們使用這個表達式樹選項,然后在運行時分析對應的lambda,查出它調用的action方法以及相關的參數類型,在表達式中指定的名稱和值等。然后我們可以在MVC URL路徑選擇系統中使用這些信息, 返回合適的URL和相關聯的HTML。
重要注意事項: 當使用這Lambda表達式方法時,我們實際上從不運行對應的Controller action方法。例如,下面的代碼并不調用我們的SearchController中"Results" action方法:
實際上,它只是返回這個HTML超鏈接:
如果這個超鏈接被用戶點擊的話,它會向服務器發回一個請求,該請求會調用SearchController的Results action方法。
單元測試路徑
asp.net mvc框架的一個核心設計原則是促進很好的測試支持。 跟mvc框架的其他部分一樣,你可以輕松地單元測試路徑和路徑匹配規則。mvc路徑選擇系統可以獨立于asp.net生成實例和運行,這意味著你可以在任何單元測試庫里裝載和單元測試路徑模式(而不用啟動web服務器),可以使用任何單元測試框架(NUnit, MBUnit, MSTest等等)。
雖然你可以在你的單元測試中直接單元測試一個asp.net mvc應用的全局RouteTable映射集合,但一般來說,讓單元測試改變或者依賴于一個全局的狀態不是一個很好的主意。一個你可以使用的較好的模式是,把你的路徑注冊邏輯放在一個象下面這樣的RegisterRoutes()輔助方法中,對作為參數傳入的RouteCollection進行操作(注:我們也許會把這個模式在下個預覽版更新中做成默認的VS模板模式):
然后,你可以編寫單元測試,創建自己的RouteCollection實例,調用Application的RegisterRoutes輔助方法,在其中注冊應用的路徑選擇規則。然后,你可以向應用發出模擬請求,核實這些請求確有注冊了的正確的控制器和action方法,而不用擔心任何副作用:
希望這個貼子提供了關于asp.net mvc路徑選擇架構工作原理的一些細節,以及你如何可以使用它來定制發布在你的asp.net mvc應用中的url的結構和布局。
在默認情形下,在你創建一個新的asp.net mvc Web應用時,它會預先定義一個你可以使用的默認的 /[controller]/[action]/[id] 路徑選擇規則,而不必手工配置或啟用什么。這應該允許你不用注冊你自己的自定義路徑選擇規則,就可以建造許多應用。但希望上面的內容示范了,如果你想對你自己的url格式做自定義結構的話,做起來并不難, mvc框架對此提供了許多的功能和靈活性。
【編輯推薦】
- 如何在IIS6.0中部署asp.net mvc程序
- 用Winform傻瓜式搭建asp.net mvc框架
- ASP.NET Session失效的編程思路
- ASP.NET Session 狀態的存儲
- 了解ASP.NET Web應用程序模型