目錄
一、理解路由的原理
- 爲什麼要定義路由?
- ASP.NET-MVC項目開發中的地位
- 路由的定義->URL訪問規則,佔用的開發量很小,但是非常重要,因爲任何請求都離不開路由
- 使用路由的好處
- 能夠根據系統需求,靈活的劃分請求規則(不同模塊請求的URL是不一樣的)
- 屏幕物理路徑,提高系統安全性,一般情況是無法根據URL分析視圖文件在站點目錄中的位置
- 用利於搜索引擎優化,可以將URL請求統一規範,以後維護中,如果頁面發生變化,URL可以保持不變
- ASP.NET-MVC項目開發中的地位
- ASP.NET MVC路由
- 路由-源自網絡中路由器的概念:負責網絡中數據傳輸路徑
- ASP.NET MVC路由系統主要職責:將各種請求路徑轉發給控制器處理
- 路由的雙向系統功能
- URL長相映射到Controller和Action:根據用戶輸入的URL觸發對應控制器並調用動作方法
- Controller和Action還可以反向映射並構造URL:根據控制器和行爲構造出URL供用戶使用
二、路由規則定義與應用
ADP.NET MVC默認路由
- RouteConfig.cs中的URL規則定義
public static RegisterRiutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name:"Default",
url:"{controller}/{action}/{id}",
defaults:new {controller = "SysAdmin",action = "Index",
id = UrlParameter.Optional}
);
}
- URL模式
- 上面的URL中的參數值是:{controller}/{action}/{id},稱之爲URL模式
- 該模式的是一串字符串,包括一些固定的"字符字面量"和"佔位符",佔位符用大括號"{}"表示
- URL模式規定了URL路徑的定義規則
- URL模式解釋
- 定義語法:{佔位符1}字面量{佔位符2}字面量...{佔位符n}字面量n
- 佔位符
- 佔位符可以是一個字符串或字符,比如"x","id","year"等
- 字面量可能是一個比較固定的字符,比較常見的是斜杆"/",也可以是字符串
- 示例:{table}/Details.aspx News/{action}/{id} {pro}-{city}/{action}
- 特殊規則:
- 不能以斜杆"/"或者波浪線"~"字符開頭,不能包含"?":如/{controller} 、~news/details{id}、{action}?id = {id}均不符合要求
- 佔位符不能連續:如{controller}{action}/{id}不符合要求
- URL模式匹配示例
- {Controller}/{action}/{id} /Student/Detail/1 /SysAdmin/AdminLogin/2
- {first}/{second}/{third} /student/Detail/1 /sysadmin/adminlogin/2
- {table}/Detail.aspx /news/Details.aspx /product/Details.aspx
- Course/{action}/{id} /Course/list/001 /Course/Detail/001
- {lanuage}-{country}/{action} /zh-cn/content /en-us/display
- {reporttype}/{year}/{month}/{day} /sales/2015/1/5
- 匹配要求
- 字面量:必須嚴格匹配,即實際請求中的字符串和路由模式中的字面量字符串必須完全一致
- 大小寫:URL模式匹配的時候不區分大小寫
- 常量:滅有包含在大括號內的信息被作爲常量對待;比如上面的Course,以及後續學習中的分區項目中路由的定義Admin/{controller}/{action}/{id}
- 思考:對同一個URL,如果多個路由都能匹配,該如何解析?
- :如果一個URL能夠在多個路由中匹配,則默認使用第一個匹配的路由
- 定義多個路由的要求
-
MapRoute( string name,//名稱 string url,//URL模式 object defaults,//默認值 object constraints,//約束 string[] namespaces//命名空間 ) public static RegisterRoutes(RouteCollection routes) { routes.MapRoute( name:"Default", url:"{controller}/{action}/{id}", defaults: new {controller = "SysAdmin",action = "Index",Id = UrlParameter.Optional}, namespace:new string[]{"對應控制器的命名空間"} ); routes.MapRoute( "blog", "{year}/{month}/{day}", new {controller = "blog",action = "index"}, constraints:new{year = @"\d{4}",month = @"\d{2}",day = @"\d{2}"}//約束 ); }
public static RegisterRoutes(RouteCollection routes) { routes.MapRoute( name:"Default", url:"{controller}/{action}/{id}", defaults: new {controller = "SysAdmin",action = "Index",Id = UrlParameter.Optional} ); routes.MapRoute( name:"Test1", url:"{first}/{second}/{third}", defaults: new {controller = "Work",action = "Index",Id = UrlParameter.Optional} ); } <a href = "/Home/Index/2015">測試多路由優先匹配順序</a>
多路由匹配選擇:如果一個URL能夠在多個路由中匹配,則默認使用第一個匹配的路由
-
關於UrlPrameter.Optionl
-
作用:該參數可以作爲路由參數的默認值,當需要讓"/Home/Index"或"/Home"能夠正常匹配,但又不希望一個無意義的值,可以使用該參數
-
-
- 路由匹配總結
- 關於{controller}/{action}
- 必不可少:在一個實際的MVC系統中,{controller}/{action}必不可少,如果缺少就會出現找不到路徑而出錯
- 約定規則:這個佔位符是MVC中約定的,並且會被解析成控制器和對應的方法
- 位置靈活:這兩個約定的佔位符可以在任意位置
- 其他佔位符
- 僅僅是佔位:比如{aa}/{ABC}/...,這裏面的aa不能被解析成控制器,ABC也不能被解析成動作方法
- 默認要求:一個路由中,如果沒有規定{controller}/{action},或者只是規定其中之一,則沒有規定的部分將使用默認值
- 匹配順序
- 優先使用:多個路由匹配一個URL則優先匹配的會使用
- 儘量避免:定義多個路由時儘量避免出現多匹配
- 關於{controller}/{action}
三、路由數據、特殊匹配、默認值與約束
- 路由數據
- 存儲方法
- 在ASP.NET MVC路由系統中,RouteData對象用來保存URL模式和實際URL匹配產生的路由數據
- 路由數據保存方式:“鍵-值”對,RouteData是視圖基類和控制器基類的屬性
- 路由和控制器的映射
- 使用路由數據
- RouteData.Values介紹
- 是RouteDataValueDictionary類型,使用方式和Dictionary<TKey,TValue>類似
- RouteData定義爲視圖和控制器基類的屬性
- 在視圖中可以遍歷RouteData.Values,來輸出路由匹配產生的路由數據
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{pathInfo}"); routes.MapRoute( name:"Default", url:"{controller}/{action}/{id}, default:new {controller = "Home",action = "Index",id = 10} ); } public ActionResult Index() { string id = RouteData.Values["id"].ToString();//通過鍵值對的取值方式取值 ViewBag.id = id; return View(); } <!--在視圖中輸出控制器中獲取的數據> @ViewBag.id</br> <!--在視圖中直接輸出> @ViewContent.RouteData.Values["id"]</br> <!--在視圖中遍歷輸出> @{ foreach(KeyValuePair<string,object> data in ViewContent.RouteData.Values) { var info = data.Key + "=" (data.Value ?? string.Empty); @info</br> } }
- RouteData.Values介紹
- 存儲方法
-
特殊URL匹配規則
- *匹配
- *用來匹配URL剩餘部分
routes.MapRoute( "default", "{controller}/{action}/{operation}/{*plus}" ); URL 路由數據 /home/index/select/a/b plus = "a/b" /home/index/update/a/b/c plus = "a/b/c" /home/index/delete/ plus = null
- *用來匹配URL剩餘部分
-
貪婪匹配規則
-
路由默認值
-
-
當URL模式中包含除"/"之外的字面量時,爲佔位符定義的默認值不起作用
-
-
路由約束
-
定義URL模式爲{year}/{month}/{day}
public static RegisterRoutes(RouteCollection routes) { routes.MapRoute( "blog", "{year}/{month}/{day}", new {controller = "blog",action = "index"}, constraints:new{year = @"\d{4}",month = @"\d{2}",day = @"\d{2}"}//約束 ); }
-
四、通過路由生成URL
- 視圖中的鏈接
- 鏈接方式
- 純靜態鏈接:直接指向鏈接地址,一般不需要改變
- 動態鏈接:爲了更好的保證web項目移植的時候路徑的正確
- Url.Content()方法
<img src = "@Url.Content("~/Images/Students/1001.png")"/> <a href = "@Url.Content("~/students/getstulist/1001">學員詳情</a>
-
不足:當路由規則變化時,需要修改所有路徑
- 鏈接方式
-
使用Action()生成鏈接
- Url.Action()方法
public string Action( string actionName, //動作方法名稱 string controllerName, //控制器名稱(沒有時,默認使用當前上下文的控制器) string routeValues //路由參數值(是一個匿名對象) ) public string Action(string actionName) public string Action(string actionName,string controllerName)
- 示例
- URL模式爲:stumanage/{controller}/{action}/{id}
@Url.Action("list","student",new{id=1001}) -->/stumanage/students/list/1001 @Url.Action("list","student",new{id = 1001,age=20,gender= 0}) -->/stumanage/students/list/1001?age=20&gender=0//溢出的參數以?和&拼接在URL模式之後 <a href = "@Url.Action("list","student",new{id = 1001,age=20,gender= 0})">學生管理</a>
- URL模式爲:stumanage/{controller}/{action}/{id}
- Url.Action()方法
-
使用ActionLink()生成超鏈接
-
Html.ActionLink()方法
MvcHtmlString ActionLink( string linkText,//鏈接文本 string actionName,string controllerName,object routeValues,//routeValue是一個匿名對象 object htmlAttributes//生成的html屬性(匿名對象) )
-
示例
URL模式爲{controller}/{action}/{id}
<a href="@Url.Action("GetStuList","student",new{id=1001,age=20,gender=0})">學生管理</a> <!--生成的鏈接爲> --> <a href="/Student/GetStuList/1001?age=20&gender=0">詳細信息</a> </br><br/> @Html.ActionLink("詳細信息","GetStuList","Student",new{id=1001,age=20,gender=0}, new {@class="stulink",title="學生姓名"}) <!--生成的鏈接爲> --> <a class="stulink" href="/Student/GetStuList/1001?age=20&gender=0" title="學生姓名">詳細信息</a>
提示:使用Html.RouteLink()代替Html.ActionLink(),可以使用Html.Action()代替Url.Action
-
五、分區項目
分區項目需要對路由的命名空間進行註冊
MapRoute(
string name,//名稱
string url,//URL模式
object defaults,//默認值
object constraints,//約束
string[] namespaces//命名空間
)
//分區項目中存在同名控制器時,需在RouteConfig文件中註冊命名空間
public static RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name:"Default",
url:"{controller}/{action}/{id}",
defaults:
new {controller = "SysAdmin",action = "Index",Id = UrlParameter.Optional},
namespace:new string[]{"對應控制器的命名空間"}
);
}