雖然在DAY 3的時候已經介紹過路由的一些基本規範,當時我們知道ASP .NET MVC 是藉由路由(Route)規範方式將URL模式連結到Controller,且網址路由是定義在「App_Start」資料夾中的「RouteConfig.cs」檔案裡。但當時沒有說明太多,今天我們再稍微深入探討相關內容。
我們先重提一下原本預設的路由規則,如下Code:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
這個路由規則的名稱name
叫做Default
,url
的規則是Domain/控制器名稱/動作方法名稱/id參數值
,輸入的網址會依此連到程式對應的控制器與動作方法。defaults
則規定了當url沒有輸入控制器名稱,預設會連到HomeController
;當url少了動作方法名稱,預設會連到Index()
動作方法;當url沒有id參數時沒關係,因為預設為UrlParameter.Optional
,代表參數可有可無。
由上述規則得知,當輸入的網址如果是:
https://localhost:44334/Home/Index
https://localhost:44334/Home/
https://localhost:44334/
都會連結到HomeController
底下的Index()
動作方法。
事實上路由規則可以有不只一組,比如下方Code,我在預設路由規則上面添加了一組新的路由規則,那麼會發生什麼事情呢?
routes.MapRoute(
name: "Test",
url: "Index123/{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
首先路由規則比對的順序是由上而下,因此輸入的url會優先比對Test
這組規則,如果比對後無法符合該規則,會繼續比對下一組,也就是Default
。因此假如輸入的網址如果是:https://localhost:44334/Index123/Home/Login
,它一樣會去執行HomeController
底下的Login()
方法。同樣道理,當網址為:
https://localhost:44334/Index123/Home/Index
https://localhost:44334/Index123/Home
https://localhost:44334/Index123/
同樣會連結到HomeController
底下的Index()
動作方法。
路由規則可以加上constraints
來設定條件約束,直接舉下方Code例子來說明,比方說網址列如果有id
參數的話,我們除了在動作方法將它的型別設為int
以外,又希望要求輸入的值應該要是正數(>0)的話可以怎麼做呢?
public class TestController : Controller
{
// GET: Test
public ActionResult ShowContent(int id)
{
return Content($"會員編號是: {id}");
}
}
針對這樣的條件需求,我們可以在路由規則上增加constraints
來限制條件,如下寫法:
routes.MapRoute(
name: "Test",
url: "Test/{id}",
defaults: new { controller = "Test", action = "ShowContent" },
constraints: new { id = @"\d+" }
);
這邊利用了正規表達式(Regular Expression)來限制id
參數必須為一或多個0-9整數組合的值,當id
輸入負數時會顯示下圖錯誤:
除了在RouteConfig.cs
設定路由規則以外,在控制器與動作方法上新增Route Attribute是另外一種限制路由的方式,要啟用屬性路由的話,必須先在RouteConfig.cs
新增如下Code:
routes.MapMvcAttributeRoutes();
而且新增的位置必須於所有路由規則之前,如下圖所示:
加入後就可以在控制器上方增加[RoutePrefix()]
屬性,以及在動作方法上增加[Route()]
屬性。
上圖所示的[RoutePrefix("Main")]
屬性表示必須有該路由前綴才能夠進入該控制器,而不是依照原本的Home
。
搭配[Route()]
與[Route("Index")]
表示要進入該動作方法的路由只能是Index
或不加也可以。因此能夠進入此方法的url就只能是:
https://localhost:44334/Main/Index
https://localhost:44334/Main/
而以下原本的url皆無法進入:
https://localhost:44334/Home/Index
https://localhost:44334/Home/
https://localhost:44334/
最後稍微講一下在RouteConfig.cs
最上面一行有個
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
這行意思是當路由格式為{resource}.axd/{*pathInfo}
的情形下,會忽略路由比對。主要是方便相容Webform頁面可以並存於MVC專案內,詳細可以參考以下文章內容:
MVC專案routes.IgnoreRoute的實際用途
今天比較詳細探討路由的觀念,其實相關資料我也是上網查了許多才比較清楚一點,如果有說明不正確或不完整的地方,再麻煩大神們指教了~