當今天有個網址的需求是 http://abcdefg.com/【使用者暱稱】,使用者暱稱帶到誰的就會到個人頁網址,EX : http://abcdefg.com/toyo 就連到Toyo個人頁面,http://abcdefg.com/steven就連到Steven個人頁,那我們Router可以寫成
1 2 3 4 5 6 7
| [Route("~/toyo")] [Route("~/steven")] public ActionResult Content() { return View(); }
|
這樣寫的確兩個網址都能連到了,但卻抓不到UserName所以不知道怎麼顯示個人頁,調整一下
1 2 3 4 5 6 7
| [Route("~/{UserName}")] public ActionResult Content(string userName) { ViewBag.Name = userName; return View(); }
|
下個問題來了,Tom明明不是這邊的用戶,卻也會導到這個Action,導致後端抓不到對應資料顯示錯誤,能不能只有abcdefg.com/Toyo 跟 abcdefg.com/Steven 的時候才導來這,其他什麼阿貓阿狗,甚至是常用的Index、Home、Menu之類的不會跑錯。
這時候RouteConstraint就派上用場了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class UserNameConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { if (values.ContainsKey(parameterName)) { var UserName = values[parameterName] as string;
return UserName.ToLower() == "toyo" || UserName.ToLower() == "steven"; }
return false; } }
|
接著在RouteConfig註冊這組Constraint,讓RouteAttribute可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var constraintsResolver = new DefaultInlineConstraintResolver(); constraintsResolver.ConstraintMap.Add("MustUserName", typeof(UserNameConstraint)); routes.MapMvcAttributeRoutes(constraintsResolver); } }
|
將RouteAttribute的UserName加上這個限制
1 2 3 4 5 6 7
| [Route("~/{UserName:MustUserName}")] public ActionResult MyContent(string userName) { ViewBag.Name = userName; return View(); }
|
這樣只要UserName不是帶Toyo或是Steven的就都不會導到這個Action了。
其實RouteConstraint官方已經提供一下基礎的限制可以使用,例如一定要是Int,字串長度之類的方便用法,而且更重要的是在這案例之中,使用者名稱我們是寫死的,只要把那段改成抓外部來源,例如資料庫之類的,這樣就能後台使用者有新增時,Route的限制就自動更新了
延伸閱讀:
Attribute Routing in ASP.NET MVC 5
DemoShop : ASP.NET MVC Route 自訂限制條件(constraints)的技巧