<strong>一. 在RouteConfig文件中創建并注冊一條簡單路由:</strong>
Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
routes.Add("MyRoute", myroute);
使得可以在瀏覽器中通過http://localhost:xxxxx//Customer/List, 或者http://localhost:26399/Admin/Index 等形式進行訪問:
其中Customer表示控制器CustomerController類,List代表該類中的List方法。
除了上述寫法,還可以寫為:
routes.MapRoute("MyRoute", "{controller}/{action}");
此時,RouteConfig.cs文件中的內容為:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
//Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
//routes.Add("MyRoute", myroute);
routes.MapRoute("MyRoute", "{controller}/{action}");
}
}
現在,訪問默認URL時,會出現錯誤,因為默認的URL被表示為"~/"送給路由系統,并不滿足任何片段。
<strong>二. 定義默認值</strong>
在MapRoute方法中添加:
routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" });
對于兩片段的URL,如/Home/Index,工作原理不變,對于單片段的URL,會給action變量自動賦值Index,也就是說可以請求/Home 。
更近一步,使用:
routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
此時,映射的URL匹配表為:
片段數量=0:
mydomain.com => controller = Home action = Index
片段數量=1:
mydomain.com/Customer => controller=Customer action = Index
片段數量=2:
mydomain.com/Customer/List => controller = Customer action = List
<strong>三.靜態URL片段</strong>
并非所有片段都需要可變,如下:
routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
這個URL模式將只匹配含有3個片段的URL,第一個必須是Public。
若采用下面的方式:
routes.MapRoute("", "X{controller}/{ation}");
這條路由模式匹配的方式為:匹配兩片段URL,第一個片段以X打頭。此時,訪問http://localhost:26399/XHome/Index 即可匹配。
以上三條路由的順序為:
public static void RegisterRoutes(RouteCollection routes)
{
//Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
//routes.Add("MyRoute", myroute);
routes.MapRoute("", "X{controller}/{action}");
routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
}
路由系統根據最先被定義的模式來匹配輸入URL,只有在不匹配的情況下,才會繼續對下一條路由進行處理,直到找到匹配的一條,或者嘗試完所有條目。
因此,<b>必須首先定義較為具體的路由。</b>
可以根據靜態片段和默認值為特定的路由創建一個別名。如以前用的是一個ShopController,現在用HomeController代替,則:
public static void RegisterRoutes(RouteCollection routes)
{
//Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
//routes.Add("MyRoute", myroute);
routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });
routes.MapRoute("", "X{controller}/{action}");
routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
}
第一條路由匹配模式為:兩片段URL,第一個片段必須是Shop,action的值為第二個URL片段。但是該模式不含controller的可變片段,因此一定會使用默認值,即/Shop/Index會轉換為/Home/Index。
更進一步:
routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });
<strong>四.定義自定義片段變量</strong>
首先注釋之前的所有語句,如下:
public static void RegisterRoutes(RouteCollection routes)
{
//Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
//routes.Add("MyRoute", myroute);
//routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });
//routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });
//routes.MapRoute("", "X{controller}/{action}");
//routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
//routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultID" });
}
最后一條路由的URL模式定義了標準的controller和action變量,和一個id的自定義變量。將匹配0~3個片段的URL,第三個片段賦值給id,沒有第三個片段時會采用默認值。
可以通過RouteData.Values屬性,在Action中訪問任何一個片段變量:
public ActionResult CustomVariable()
{
ViewBag.CustomVariable = RouteData.Values["id"];// 此時訪問http://localhost:26399/Home/CustomVariable/Hello,CustomVariable中是Hello
return View();
}
此外,如果把Action中的參數的名稱變為與URL中的變量相匹配,MVC會把URL中獲得的值作為參數傳遞給Action方法,如:
給CustomVariable這個Action方法加上id參數:
public ActionResult CustomVariable(string id)
{
ViewBag.CustomVariable = id;
return View();
}
URL變為:http://localhost:26399/Home/CustomVariable/5
則,5被當作參數id傳遞給Action方法:
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>The custom variable is : @ViewBag.CustomVariable</div>
</body>
</html>
此時,返回的View顯示:The custom variable is : 5
<strong>4.1 定義可選URL片段</strong>
可選URL片段:用戶不需要指定,但又沒有指定默認值的片段。
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
這條匹配的工作模式:
片段=0:xxx.com
=>
controller = Home action = Index
片段=1:xxx.com/Customer
=>
controller = Customer action = Index
片段=2:xxx.com/Customer/List
=>
controller = Customer action = List
片段=3:xxx.com/Customer/List/All
=>
controller = Customer action = List id=All
<strong>4.2 定義可變長路由</strong>
通過制定一個全匹配的片段變量,通過*作為前綴,可以支持可變片段數。
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
工作模式為:
/:controller = Home action = Index
/Customer:controller=Customer action=Index
/Customer/List:controller=Customer action=List
/Customer/List/All:controller = Customer action = List Id=All
/Customer/List/All/Delete:controller = Customer action = List Id=All catchall = Delete
/Customer/List/All/Delete/Perm :controller = Customer action = List Id = All catchall=Delete/Perm
<strong>4.3 按命名空間區分Controller優先順序</strong>
此時,Controllers文件夾中有一個HomeController類,假如在另一個文件夾中再創建一個HomeController類,訪問時會報錯:
解決方法如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "UrlsAndRoutes.AdditionalControllers" });
}
以上代碼告訴MVC框架,先考察URLsAndRoutes.AdditionalControllers命名空間。
注意:一條路由中的命名空間具有相等優先級,若:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "UrlsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers" });
}
會報同樣的錯誤。
如果希望對某個命名空間中的某個Controller優先,又需要解析另一個命名空間中的其他Controller,需要創建多條路由:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.AdditionalControllers" });
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.Controllers" });
}
此時,若用戶的第一個片段為Home,會運用第一條路由,并以AdditionalControllers文件夾中的Controller為目標。除此之外的其它請求,使用Controllers文件夾中的Controller處理。
還可以在所指定的命名空間中找不到匹配時,不在搜索其它地方,如下:
Route MyRoute = routes.MapRoute("AddControllerRoute", "Home/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "UrlsAndRoutes.AdditionalControllers" });
MyRoute.DataTokens["UseNamespaceFallback"] = false;
<strong>五.約束路由</strong>
<strong>5.1 用正則表達式約束路由</strong>
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^H.*" },
new[] { "URLsAndRoutes.Controllers" });
}
該路由匹配controller變量值以“H”打頭的URL。
注意,首先運用默認值,再檢查約束。因此,若請求的URL是 / ,會把默認值“Home”運用于controller,然后再檢查約束。
<strong>5.2 將一條路由約束到一組指定的值</strong>
可以使用 | 把一條路由約束到一組指定的片段變量值
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^H.*", action = "^Index$|^About$"},
new[] { "URLsAndRoutes.Controllers" });
}
這條約束允許這個路由只匹配action片段的值為“Index”或者“About”的URL。
<strong>5.3 使用HTTP方法約束路由</strong>
可以約束路由,使得它們只匹配指定的HTTP方法進行請求的URL。
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new
{
controller = "^H.*",
action = "^Index$|^About$",
httpMethod = new HttpMethodConstraint("Get")
},
new[] { "URLsAndRoutes.Controllers" });
}
上述語法中,httpMethod可以是任何名字,只要是一個HttpMethodConstraint實例即可。
也可以使用類型和值約束,如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new
{
controller = "^H.*",
action = "^Index$|^About$",
httpMethod = new HttpMethodConstraint("Get"),
id = new RangeRouteConstraint(10, 20)
},
new[] { "URLsAndRoutes.Controllers" });
}
這條路由使用了RangeRouteConstraint類,檢查提供的片段變量的值是否是10到20中的一個有效的int類型值。
假設要確保路由將僅僅匹配包含字母字符并且至少含有6個字符的字符串值:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new
{
controller = "^H.*",
action = "^Index$|^About$",
httpMethod = new HttpMethodConstraint("Get"),
id = new CompoundRouteConstraint(new IRouteConstraint[]
{
new AlphaRouteConstraint(),
new MinLengthRouteConstraint(6)
})
},
new[] { "URLsAndRoutes.Controllers" });