接着上篇講MVC的路由,MVC 應用程序可使用路由的 URL 生成功能,生成指向操做的 URL 連接。 生成 URL 可消除硬編碼 URL,使代碼更穩定、更易維護。 此部分重點介紹 MVC 提供的 URL 生成功能,而且僅涵蓋 URL 生成工做原理的基礎知識。 IUrlHelper
接口用於生成 URL,是 MVC 與路由之間的基礎結構的基礎部分。 在控制器、視圖和視圖組件中,可經過 Url
屬性找到 IUrlHelper
的實例。html
// // mvc 框架的ControllerBase類下 //摘要: // Gets or sets the Microsoft.AspNetCore.Mvc.IUrlHelper. public IUrlHelper Url { get; set; }
下面示例中,經過使用IUrlHelper接口在index頁面生成指向另外一操做Destination的 URL超鏈接。瀏覽器
[Route("Home/Index")] public IActionResult Index() { // Generates /Home/Destination var url = Url.Action("Destination"); var urlAddress = "<a href=\"" + url + "\" >Click on to the Destination</a>"; ViewData["url"] = urlAddress; return View(); } public IActionResult Destination() { return View(); } // Index.cshtml @Html.Raw(ViewData["url"].ToString())
當加載index頁面後,點擊超鏈接"Click on to the Destination" 將進入後臺控制器的Destination操做中。mvc
上面的 Url.Action 示例假定使用傳統路由,但 URL 生成功能的工做方式與屬性路由類似,只不過概念不一樣。 在傳統路由中,路由值用於擴展模板。controller 和 action 的路由值一般出如今該模板中, 這種作法可行是由於經過路由匹配的 URL 遵照某項約定。 這裏的擴展模板指的是routes.MapRoute來添加路由規則約定。app
在屬性路由中,controller
和 action
的路由值不能出如今模板中(也就是不會使用routes.MapRoute),它們用於查找要使用的模板。框架
//首先不用傳統路由,去掉了routes.MapRoute public void Configure(IApplicationBuilder app) { app.UseMvc(); } [Route("")] public IActionResult Index() { // Generates /custom/url/to/destination var url = Url.Action("Destination"); var urlAddress = "<a href=\"" + url + "\" >"+url+"</a>"; ViewData["url"] = urlAddress; return View(); } [HttpGet("custom/url/to/destination")] public IActionResult Destination() { return View(); }
生成以下圖所示 :因此會生成與httpget配置的路徑同樣,是由於屬性路由下的url生成,它們用於查找要使用的模板。MVC 生成一個包含全部屬性路由操做的查找表,並匹配 controller 和 action 的值,以選擇要用於生成 URL 的路由模板。asp.net
Url.Action
(IUrlHelper
. Action
) 以及全部相關重載都基於這樣一種想法:用戶想經過指定控制器名稱和操做名稱來指定要連接的內容。測試
[Route("")] public IActionResult Index() { // Generates /Home/Destination/1?color=red var url = Url.Action("Destination","Home",new { id=1 , color="red"}); var urlAddress = "<a href=\"" + url + "\" >" + url + "</a>"; ViewData["url"] = urlAddress; return View(); } public IActionResult Destination(int id,string color) { return View(); }
IUrlHelper 還提供 Url.RouteUrl 系列的方法。 這些方法相似於 Url.Action。Url.RouteUrl 指定一個路由名稱,以使用特定路由來生成 URL,一般不指定控制器或操做名稱。ui
[Route("")] public IActionResult Index() { // Generates /custom/url/to/destination var url = Url.RouteUrl("Destination_Route"); var urlAddress = "<a href=\"" + url + "\" >Click on to the Destination</a>"; ViewData["url"] = urlAddress; return View(); } [HttpGet("custom/url/to/destination", Name = "Destination_Route")] public IActionResult Destination() { return View(); }
(1)在 HTML 中生成 URL: IHtmlHelper 提供 HtmlHelper 方法 Html.BeginForm 和 Html.ActionLink,可分別生成 <form> 和 <a>元素。 這些方法使用 Url.Action 方法來生成 URL,而且採用類似的參數。編碼
(2)在action中重定向:RedirectToAction("Index"); url
區域是一種 MVC 功能,用於將相關功能整理到一個組中,做爲單獨的路由命名空間(用於控制器操做)和文件夾結構(用於視圖)。 經過使用區域,應用程序能夠有多個名稱相同的控制器,只要它們具備不一樣的區域。 經過向 controller
和 action
添加另外一個路由參數 area
,可以使用區域爲路由建立層次結構。
下面是mvc文件結構,對於users控制器,在視圖層多了一級Manage文件夾。如何使users控制器中AddUser操做關聯AddUser.cshtml呢,下面使用區域路由來實現:
app.UseMvc(routes => { //用於名爲 Blog 的區域 routes.MapAreaRoute("blog_route", "Blog","Manage/{controller}/{action}/{id?}"); /* * 註釋的MapRoute與上面的區域路由做用同樣 routes.MapRoute("blog_route", "Manage/{controller}/{action}/{id?}", defaults: new { area = "Blog" }, constraints: new { area = "Blog" }); */ routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
//控制器上應用區域路由 [Area("Blog")] public class UsersController : Controller { // GET: /<controller>/ public IActionResult AddUser() { return View(); } }
在瀏覽器中輸入/Manage/Users/AddUser 將自動進入AddUser()中,這是由於當前路由:Manage/{controller}/{action}/{id?}符合blog模板,因此使用Blog區域路由。
實現IActionConstraint最簡單的方法是建立派生自 System.Attribute 的類,並將其置於操做和控制器上。MVC 將自動發現任何應用屬性IActionConstraint的操做和控制器。
在下面的示例中,約束基於路由數據中的國家/地區代碼選擇操做,開發人員負責實現Accept
方法,當路由中id值爲en-US時Accept
方法返回 true
以表示該操做是匹配項,一切按正常解析返回客戶端。 若是Accept
方法返回false將不執行IActionConstraint標記的action,向客戶端返回404錯誤。
//定義ActionConstraint屬性約束 public class CountrySpecificAttribute : Attribute, IActionConstraint { private readonly string _countryCode; public CountrySpecificAttribute(string countryCode) { _countryCode = countryCode; } public int Order { get { return 0; } } public bool Accept(ActionConstraintContext context) { return string.Equals( context.RouteContext.RouteData.Values["id"].ToString(), _countryCode, StringComparison.OrdinalIgnoreCase); } }
//應用路由的action約束,而且路由中id值爲en-US [CountrySpecific("en-US")] public IActionResult Privacy(string countryCode) { return View(); }
在瀏覽器測試時:若是輸入http://localhost:30081/home/Privacy/zh-cn,則網頁顯示404。若是輸入http://localhost:30081/home/Privacy/en-US 則符合約束,網頁顯示正常。
參考文獻
官方資料:asp.net core routing