ASP.NET MVC框架中的路由用途:
- 匹配传入的请求(该请求不匹配服务器文件系统的文件),并将这些请求映射到控制器操作上
- 构造传入的URL,用来响应控制器操作
URL重写:首先获取一个进入的URL请求然后把它重写成网站可以处理的另一个URL,例如通过浏览器进来的URL是“UserProfile.aspx?ID=1”,然后它被重写为“UserProfile/1.aspx”
路由:就是从URL模板开始,它指定了与路由相匹配的模式;路由定义可以作为控制类或操作方法的特性,路由可以指定它的URL及其默认值;还可以约束URL的各个部分,提供关于路由如何以及何时与传入的请求URL相匹配的严格控制
特性路由
- MVC Web应用程序中,Global.asax.cs文件中Application_Start方法调用了RouteConfig配置文件的RegisterRoutes方法,重写一下,可以调用特性路由
- 传入路由特性的字符串叫做路由模板,它是一个模式匹配规则,决定这个路由是否符合适用于传入的请求;如果匹配,MVC就运行路由的操作方法
1 public static void RegisterRoutes(RouteCollection routes){ 2 //通过调用MapMvcAttributeRoutes注册方法让RegisterRoutes方法启动特性路由 3 routes.MapMvcAttributeRoutes(); 4 } 5 //[Route("~/")]//无论加不加前缀都可以通过 / 访问该页面 6 [Route("")]//可以通过 / 访问该页面 7 [Route("Home")]//可以通过 /home 访问该页面 8 [Route("Home/index")]//可以通过 /home/index 访问该页面 9 public ActionResult Index(){ 10 return View(); 11 } 12 [Route("Home/{id}")]//可以通过 /home/id参数值 访问该页面 13 public ActionResult Details(int id){ 14 return View(); 15 } 16 [Route("{year}/{month}/{day}")]//可以通过 /year参数值/month参数值/day参数值 访问该页面 17 public ActionResult ShowDate(string year,string month,string day){ 18 return View(); 19 }
- 在一个控制器中所有的方法所遵循的模板路由都具有相似的路由模板,在控制器类上定义路由,可以使用一个叫做action的特殊路由参数,它可以作为任意操作的名称的占位符;action参数的作用相当于在每个操作方法上单独添加路由,并静态输入操作名
- 对于上述方法,明显有大量重复性,每个路由都是有home开头,所以可以通过RoutePrefix,仅仅在控制器类上定义,这样前缀会自动给它们加上home/
1 [Route("home/{action}")]//访问方法about可以使用 /home/about 2 public class HomeController : Controller{} 3 [RoutePrefix("home")] 4 [Route("{action}")] 5 public class HomeController : Controller{ 6 [Route("~/")]//可以通过 / 访问该页面 7 [Route("")]//可以通过 /home 访问该页面 8 [Route("index")]//可以通过 /home/index 访问该页面 9 public ActionResult Index(){ 10 return View(); 11 } 12 }
- 路由约束:对路由模板进行约束,又叫做内联约束,可以进行bool、datetime、decimal、double、float、guid、int、long这样的参数类型约束;又可以使用minlength、maxlength约束字符串的长度最小、最大;length(n)和length(m,n)分别约束长度为n和长度为m到n;min、max约束int类型的最小值最大值;range(m,n)约束int的范围;alpha约束只包含字符A-Z和a-z;regex()是正则表达式约束
1 [Route("Home/{id:int}")]//可以通过 /home/id参数值 访问该页面 2 public ActionResult Details(int id){ 3 return View(); 4 }
- 路由的默认值:{action=Index}为action参数定义了默认值,该默认情况就允许路由匹配没有action参数的请求,即可以使用/home来访问/home/index页面
- 路由的可选参数:使用?约定这个参数可以不传
1 [Route("Home/{action=Index}")] 2 [Route("Home/{id?}")]
传统路由
- MapRoute方法采用的就是路由名称和路由模板,在路由的路径段中允许字面值和路由参数混合在一起,它仅仅有的限制就是不允许有两个连续的路由参数
- {controller}/{action}/{id}可以与/home/index/1匹配;service/{action}-{format}可以与/service/display-xml匹配;
1 public static void RegisterRoutes(RouteCollection routes){ 2 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//使得路由机制忽略指定路由 3 //routes.Add(new Route("", new StopRoutingHandler()));//使得路由机制忽略指定路由 4 routes.MapRoute( 5 name: "Default", 6 url: "{controller}/{action}/{id}", 7 //约定默认值和id为可选参数 8 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 9 ); 10 routes.MapRoute( 11 "blog", 12 "{year}/{month}/{day}", //可以直接使用 /2014/02/23 来进行访问 13 new { controller = "Home", action = "showdate" },//默认规定控制器上的操作名 14 new { year = @"d{4}", month = @"d{2}", day = @"d{2}" });//约束限制 15 }
- catch-all参数:允许路由匹配任意个段的URL,只能作为路由模板的最后一段;例如/query/select/a/b/c,extrastuff=“a/b/c”,query/select/,extrastuff=null
1 routes.MapRoute("","query/{query-name}/{*extrastuff}")
- {filename}.{ext}中对于请求URL(/Foo.xml.aspx),filename=“Foo.xml” ext=“aspx”;My{location}-{sublocation}对于请求的URL(/MyHouse-dwelling),location=”House“ sublocation=”dwelling“,{foo}xyz{bar}对于请求URL(/xyzxyzxyzblah),foo=”xyxxyx“ bar=”blah“ 对于.这样的分割符,它们会尽可能的多匹配文本,直到不能在进行匹配为止
- 选择传统路由:想要集中配置所有路由;使用自定义约束对象;存在现有可以工作的应用程序,而不想修改应用程序;
- 选择特性路由:想把路由与操作代码保存在一起;创建新的应用程序,或者对现有的应用程序进行巨大修改;
- 在结合使用传统路由和特性路由的时候,建议在路由表中,把特性路由放在传统路由之前
- 路由的调试:在web.config文件的appSetting节点添加一个设置
1 <add key="RouteDebugger:Enabled" value="true" />
- 在对于传统路由来说,对路由进行命名,可以使得在使用@Html.RouteLink方法进行更好的调用路由,不会出现调用的路由模板二义性
1 @Html.RouteLink( 2 linkText:"route:Text", 3 routeName:"text",//路由的名称 4 routeValue:new { controller="",action="",id= } 5 )
MVC区域
- 可以为每一个区域创建类配置路由,所创建的类派生自AreaRegistration类,还有重写其中的AreaName和RegisterArea成员,在MVC的项目模板中,Global.asax文件中的Application_Start方法中就有调用AreaRegistration.RegisterAllAreas()来注册 ASP.NET MVC 应用程序中的所有区域
- 假如在不同区域中有两个同名的控制器,例如Home控制器,就会出现区域路由冲突,两个控制器匹配一个路由;
- 传统路由中直接使用控制器类的命名空间
- 特性路由中使用RouteArea特性,这样这个控制器类的所有特性路由都使用区域名称作为路由前缀,例如/admin/home/index;如果想使用一个不同的路由前缀,可以使用可选的AreaPrefix属性,
routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } new[]{ ""}//一组控制器类的命名空间 ); [RouteArea("admin")] [RouteArea("admin",AreaPrefix="manage")]
Web Forms路由:可以使用Page.RouteData访问路由参数值,使用Page.GetRouteUrl("",new{参数=""})来生成URL