目录
一、理解路由的原理
- 为什么要定义路由?
- 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[]{"对应控制器的命名空间"}
);
}