2023年7月4日发(作者:)
教程五:中的路由⼀、概述在 MVC架构中,控制器在3⼤核⼼构件中处于中⼼地位,通过控制器⽀配模型和视图,然⽽从浏览器发出的请求到控制器还需要路由的协助,路由将特定的请求和控制器的动作对应起来。在 MVC程序中,路由主要有两⽅⾯的职责:1. 与⼊站的请求相匹配,将这些请求映射到控制器的动作中。2. 构造出站的URL,这些URL可以响应控制器的动作。⼆、路由原理1、注册路由先看中的代码:⽹站启动的时候执⾏Application_Start⽅法,通过erRoutes()这段代码进⾏路由的注册,在RegisterRoutes上⾯F12转到定义,可以查看该⽅法,其实就是App_Start⽂件夹下⾯的RouteConfig类,该类定义如下:using System;using c;using ;using ;using ;using g;namespace ASPNETMVCDemo{ /// /// RouteCollection 所有路由的集合 /// public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表⽰忽略路由 只要URL满⾜这个正则规则,就不使⽤路由 // .axd 是因为iis6给没有后缀的请求加个asd,然后⽀持MVC的请求 Route("{resource}.axd/{*pathInfo}"); // 默认路由规则 // ⾥⾯使⽤的是命名参数,顺序可以改变 te( // 路由名称 RouteCollection是个字典 每个路由都要有⾃⼰的名称,相同名称的路由会被覆盖 name: "Default", // url的正则规则,去掉域名和端⼝后的地址进⾏匹配 url: "{controller}/{action}/{id}", // 默认值 defaults: new { controller = "Home", action = "Index", id = al } ); } }}注册路由其实就是把路由规则添加到RouteCollection路由集合中。解释说明:1. RegisterRoutes⽅法是在应⽤程序启动时(Application_Start)被调⽤执⾏的。2. RegisterRoutes⽅法的作⽤:注册路由。它的参数是⼀个集合对象,这个集合对象就是⽤来保存多项路由数据的。⼀项路由数据实际上就是某种形式的URL路径和控制器及其Action的关系,根据这个关系,MVC才能执⾏到控制器。3. 那么怎么添加这种路由数据呢?即调⽤RegisterRoutes⽅法⾥⾯的te⽅法。该⽅法的第⼀个参数是路由的名称,类似于Dictionary字典⾥⾯的key。第⼆个参数表⽰的是URL或者是地址。第三个参数是⼀个匿名类型,表⽰该路由相关的默认数据,可以看作⼀个字典。4. 我们注意到第⼆个参数其实就是占位符表⽰的URL,这个占位符是⽤⼤括号和⾥⾯的字符串表⽰的。可以看出⾥⾯不是某种硬编码的URL地址(这⾥的controller代表所有的控制器,⽽不是某⼀个具体的控制器。同理,action也是代表所有的⽅法,⽽不是某⼀个具体的action⽅法),这样就增加了灵活性,就是⽤“/”把URL分成三部分。还有我们注意到占位符表⽰的URL是没有域名的,这个是允许的,这种匹配是不考虑域名的。5. 在 MVC中我们见得最多的是“{controller}/{action}/{id}”这种形式的URL,那么controller和action这两个单词是否有特殊的⽤途呢,能不能改变这两个单词的写法。答案是不能的。这时因为会把controller、action和id当做字典或集合的key值来存储对应的URL⽚段,这样框架在处理时,会读取键名为controller的数据,⽐如Home,然后得到要执⾏的控制器是HomeController。同样会从字典中读取键名为action的数据,⽐如Index,然后得到要执⾏的Action⽅法是Index。如果这两个单词写错了,就执⾏不到相应的controller和action⽅法了。所以⼀定要记住写成controller和action是⼀种约定,其他参数的定义就没有这种要求了。但是action和controller的位置可以修改。修改URL⾥⾯的controller和action,代码如下:using System;using c;using ;using ;using ;using g;namespace ASPNETMVCDemo{ /// /// RouteCollection 所有路由的集合 /// public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表⽰忽略路由 只要URL满⾜这个正则规则,就不使⽤路由 // .axd 是因为iis6给没有后缀的请求加个asd,然后⽀持MVC的请求 Route("{resource}.axd/{*pathInfo}"); // 默认路由规则 // ⾥⾯使⽤的是命名参数,顺序可以改变 te( // 路由名称 RouteCollection是个字典 每个路由都要有⾃⼰的名称,相同名称的路由会被覆盖 name: "Default", // url的正则规则,去掉域名和端⼝后的地址进⾏匹配 url: "{controller1}/{action1}/{id}", // 默认值 defaults: new { controller = "Home", action = "Index", id = al } ); } }} 然后运⾏程序查看结果:这时程序运⾏出错,所以说controller和action千万不能写错。把controller和action改回正确的,然后颠倒controller和action的位置,代码如下:using System;using c;using ;using ;using ;using g;namespace ASPNETMVCDemo{ /// /// RouteCollection 所有路由的集合 /// public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表⽰忽略路由 只要URL满⾜这个正则规则,就不使⽤路由 // .axd 是因为iis6给没有后缀的请求加个asd,然后⽀持MVC的请求 Route("{resource}.axd/{*pathInfo}"); // 默认路由规则 // ⾥⾯使⽤的是命名参数,顺序可以改变 te( // 路由名称 RouteCollection是个字典 每个路由都要有⾃⼰的名称,相同名称的路由会被覆盖 name: "Default", // url的正则规则,去掉域名和端⼝后的地址进⾏匹配 url: "{action}/{controller}/{id}", // 默认值 defaults: new { controller = "Home", action = "Index", id = al } ); } }} 在运⾏程序查看结果:2、路由匹配2.1、匹配⽅式⼀看下⾯的截图:解释说明:1. {parameter}:花括弧加任意长度的字符串表⽰模糊匹配,字符串不能定义成controller和action。默认路由规则就是使⽤模糊匹配,没有指明具体是哪个控制器⾥⾯的哪个action⽅法。2. 字⾯量即⼀个常数字符串,这个字符串可以在⼤括弧与⼤括弧之间,也可以在最前⾯或最后⾯。3. 两个⼤括弧之间没有任何的字⾯量是不可以的。 看下⾯的⽰例:⾸先修改Home控制器⾥⾯的Index⽅法,修改后的代码如下:using System;using c;using ;using ;using ;namespace llers{ public class HomeController : Controller { public ActionResult Index() { string paras = ""; // 遍历获取参数值 foreach(KeyValuePair keyValue in ) { paras += ($"{}={} "); } // 通过ViewData向页⾯传值 ViewData["msg"] = paras; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }} 修改对应的视图,在界⾯展⽰ViewData["msg"]的值:@{ = "Home Page";} is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.
Learn more »
@ViewData["msg"]
Getting started
MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development.
Learn more »
Get more libraries
NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.
Learn more »
Web Hosting
You can easily find a web hosting company that offers the right mix of features and price for your applications.
Learn more »
1、使⽤{parameter}做模糊匹配其实就是默认路由规则:te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al }); 运⾏程序查看结果:2、使⽤字⾯量做精确匹配路由规则如下代码所⽰:te( name: "const", url: "admin/{controller}/{action}");3、不允许连续的URL参数路由规则如下:te( name: "blx", // 错误的URL // url: "{language}{country}/{controller}/{action}" url: "{language}-{country}/{controller}/{action}");2.2、匹配⽅式⼆看下⾯截图:解释说明:1. 使⽤“*”来匹配URL剩余的部分,如*plus放在⼀个表达式的尾部,最后尾部的URL会保存为plus为键名的字典值。看下⾯的路由规则:te( name: "RouteRule", url: "{controller}/{action}/{query-name}/{*plus}");2.3、匹配⽅式三看下⾯截图:解释说明:1. 在URL表达式中有⼀种特殊的情况,就是URL表达式可能和实际的URL有多种匹配情况,这时候遵守贪婪匹配的原则(即从后往前进⾏匹配)。路由规则1:te( name: "tlppone", url: "{controller}/{action}/{filename}.{ext}");路由规则2:te( name: "tlpptwo", url: "{controller}/{action}/{foo}xyz{bar}");完整路由规则代码如下:using System;using c;using ;using ;using ;using g;namespace ASPNETMVCRoute{ public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { Route("{resource}.axd/{*pathInfo}"); // 使⽤字⾯量做精确匹配 // localhost:64957/admin/home/index te( name: "const", url: "admin/{controller}/{action}" ); // 不允许连续的URL参数 // localhost:64957/chinese-china/home/index te( name: "blx", // 错误的URL // url: "{language}{country}/{controller}/{action}" url: "{language}-{country}/{controller}/{action}" ); // 使⽤*号匹配URL剩余部分 // localhost:64957/home/index/ 与第⼀个和第⼆个路由规则都匹配,显⽰第⼀个,说明路由匹配的顺序是从上往下 // localhost:64957/home/index/123/wqer_1234 te( name: "RouteRule", url: "{controller}/{action}/{query-name}/{*plus}" ); // 贪婪匹配 // localhost:64957/home/index/ te( name: "tlppone", url: "{controller}/{action}/{filename}.{ext}" ); // 贪婪匹配2 // localhost:64957/home/index/xyzxyzxyzwer23 te( name: "tlpptwo", url: "{controller}/{action}/{foo}xyz{bar}" ); te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al } ); } }}3、URL参数默认值3.1、参数默认值⼀看下⾯的截图:解释说明:1. 如上图所⽰,我们使⽤了参数的默认值,上图下⽅的URL都是匹配这个路由的,如果没有使⽤默认值,那么就只能使⽤localhost/home/index/1这种完整形式的URL地址了。路由规则代码如下:// 参数默认值⼀te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al });3.2、参数默认值⼆看下⾯截图:解释说明:1. ⾸先我们说的路由项只提供部分URL⽚段默认值的情况,⼀条规则就是如果在路由项中使⽤默认值,但是没有提供全部默认值,那么没有提供默认值的必须通过URL提供。在上⾯截图中,控制器必须在URL⾥⾯提供。路由规则如下:// 参数默认值⼆:默认值不提供的必须通过URL提供te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { action = "Index", id = al }); 这时直接运⾏程序,因为没有提供controller,所以程序会报错:3.4、参数默认值三解释说明:1. 如果只提供了部分参数,⽽且提供的部分参数是URL表达式中间的,如上图所⽰,这种情况下action是不起作⽤的,所以,这种定义默认值的⽅式是没有意义的!路由规则如下:// 参数默认值三:只提供中间参数的默认值是不起作⽤的te( name: "Default2", url: "{controller}/{action}/{id}", defaults: new { action = "Index" });
这时候需要在浏览器⾥⾯输⼊完整的URL才能访问。3.4、参数默认值四看下⾯截图:解释说明:1. 最后⼀种默认值的特殊情况,就是在URL表达式中使⽤字⾯量,注意这个字⾯量是除-之外的任意字符的组合,那么字⾯量相邻的URL参数的默认值是不起作⽤的。2. 规律:使⽤/把URL划分成若⼲个部分,如果各个部分包含了URL参数和字⾯量,那么给这些URL参数提供默认值是不起作⽤的。如图所⽰,给参数2和参数3是不起作⽤的!路由规则如下:// 参数默认值四:只提供中间参数的默认值是不起作⽤的te( name: "Default2", url: "{controller}-{action}", defaults: new { action = "Index" });4、参数值约束 假如我们想对URL后⾯的数字进⾏限制,⽐如四位数字或者两位数字,如下图所⽰,该如何限制呢?1、使⽤正则表达式如下图所⽰:解释说明:1. 在MVC的路由中我们可以对URL的各个参数定义约束,有两种约束⽅法,第⼀种是使⽤正则表达式,如上图所⽰。2. MapRoute提供了⼀个重载⽅法,就是在默认值后⾯增加了⼀个约束的参数,这个参数可以使⽤匿名类型设置值,在匿名类⾥⾯可以设置各种参数对应的正则表达式,如上图所⽰。路由规则如下:using System;using c;using ;using ;using ;using g;namespace MVCURLParaConstraint{ public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { Route("{resource}.axd/{*pathInfo}"); // 1、使⽤正则表达式设置参数值的约束 te( name: "Default1", url: "{controller}/{action}/{id}/{year}/{month}/{day}", defaults: new { controller = "Home", action = "Index", id = al }, // year是4位整数 month和day是2位整数 constraints:new { year = @"d{4}",month=@"d{2}",day=@"d{2}"} ); // 默认路由 te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al } ); } }}这时程序就报错了,说明设置的正则约束起作⽤了。2、使⽤约束类如下图所⽰:解释说明:1. 在有些时候,如果约束规则很复杂或者正则表达式很难写,或者你根本就不擅长写正则表达式,那么可以考虑第⼆种约束⽅式:约束类。2. 如上图所⽰:定义约束类就是要实现IRouteConstraint接⼝的Match⽅法,这个⽅法就是⽤来判断接⼝是否匹配的。使⽤这个约束类的⽅法也很简单,就是在以前使⽤正则表达式的地⽅,换成⽤约束类的实例赋值,如上图所⽰。 路由规则如下:using System;using c;using ;using ;using ;using g;namespace MVCURLParaConstraint{ public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { Route("{resource}.axd/{*pathInfo}"); // 2、使⽤约束类来约束参数值 te( name: "Default1", url: "{controller}/{action}/{id}/{year}/{month}/{day}", defaults: new { controller = "Home", action = "Index", id = al }, // 使⽤约束类的实例 constraints: new { year = @"d{4}", month =new MonthConstraint(), day = @"d{2}" } ); // 1、使⽤正则表达式设置参数值的约束 //te( // name: "Default1", // url: "{controller}/{action}/{id}/{year}/{month}/{day}", // defaults: new { controller = "Home", action = "Index", id = al }, // // year是4位整数 month和day是2位整数 // constraints:new { year = @"d{4}",month=@"d{2}",day=@"d{2}"} // ); // 默认路由 te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al } ); } } /// /// 对⽉进⾏约束,实现IRouteConstraint接⼝ /// 对年或者⽇进⾏约束同理 /// public class MonthConstraint : IRouteConstraint { // 实现Match⽅法 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { // values["month"]表⽰根据键名或者值 // 长度为2,并且在1到12之间表⽰匹配通过返回true,否则不通过返回false if (values["month"].ToString().Length==2 && 32(values["month"])>=1 && 32(values["month"]) <=12) { return true; } else { return false; } } }}5、路由匹配顺序如下图所⽰:解释说明:1. 如图所⽰,上⾯的URL跟哪个路由规则匹配呢?答案是匹配Default1这个路由,为什么会是这样呢?其实如果只注册单独的⼀条路由,这两条路由规则都是匹配这个URL的,这⾥有⼀个原则:如果有多条路由都和这个URL匹配,那么就是排在最前⾯的优先匹配,排在后⾯的就不在进⾏匹配。6、排除路由解释说明:1. 我们注意到RigisterRoutes⽅法中默认的第⼀句代码是Route⽅法,他的作⽤就是排除路由,⽐如上图下⾯的URL不会在路由表中匹配的,⽽是直接被忽略掉!2. 如果出了.axd以外的⽂件需要忽略,那么在IgnoreRoute⽅法⾥⾯添加需要忽略的路由即可。5、由URL到控制器先看下⾯的截图:解释说明:1. 通过前⾯路由注册的代码会最终形成⼀个路由集合的数据,可以看作是⼀个路由表(RouteTable),那么请求是如何通过URL进⼊到相应的控制器及Action⽅法的呢?2. 如上图所⽰,请求到达 MVC应⽤程序后,⾸先会经过⼀个名为“UrlRoutingModule”的HttpModule,HttpModule可以过滤每⼀个请求,UrlRoutingModule的作⽤就是根据请求的URL从路由表中查找和URL匹配的路由,然后从匹配的路由中得到⼀个名为MvcHandler的HttpHandler,之后就执⾏它的ProcessRequest⽅法,在ProcessRequest⽅法的内部找到Controller,并继续往下执⾏。3. 说到这⾥可能有疑问:某项路由数据是怎样联系到⼀个HttpHandler的呢?如下图中的源码所⽰:MapRoute⽅法实际上包含这样⼀段代码,在new的时候会初始化⼀个MvcRouteHandler对象,然后通过MvcRouteHandler的GetHttpHandler⽅法可以得到真正的处理程序MvcHandler。上⾯说的UrlRoutingModule在哪⾥呢?看下⾯截图:6、从控制器中获取URL值的⽅式从控制器中获取URL中的值共有三种⽅式:解释说明:1. tring只能获取以?分隔的参数值!2. [“id”]就是当前字典上的路由数据,通过访问键名的⽅式得到键值,⽐如URL模式匹配的字符串是id,这⾥必须是id。3. Action⽅法的参数和路由字典的参数是对应的,MVC框架在执⾏action之前会⾸先为这些参数赋值。6.1、tring控制器代码如下:using System;using c;using ;using ;using ;namespace llers{ public class HomeController : Controller { /// /// tring /// /// public ActionResult Index() { if(tring["bookid"]!=null) { string value = tring["bookid"]; ViewData["msg"] = value; } return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }}
视图也代码如下:@{ = "Home Page";}
is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.
Learn more »
@ViewData["msg"]
Getting started
MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development.
Learn more »
Get more libraries
NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.
Learn more »
Web Hosting
You can easily find a web hosting company that offers the right mix of features and price for your applications.
Learn more »
程序运⾏效果:6.2、控制器代码如下:using System;using c;using ;using ;using ;namespace llers{ public class HomeController : Controller { ///
/// tring /// ///
//public ActionResult Index() //{ // if(tring["bookid"]!=null) // { // string value = tring["bookid"]; // ViewData["msg"] = value; // } // return View(); //} ///
/// /// ///
public ActionResult Index() { string value = $"controller={["controller"]},action={["action"]}"; ViewData["msg"] = value; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }}运⾏效果:这时会遇到⼀个问题,如果在URL⾥⾯还有其他参数呢?⽐如下⾯的情况
这时候如果要获取id的值就要修改代码,那么有没有其他简便的⽅式呢?看下⾯代码:using System;using c;using ;using ;using ;namespace llers{ public class HomeController : Controller { /// /// tring /// /// //public ActionResult Index() //{ // if(tring["bookid"]!=null) // { // string value = tring["bookid"]; // ViewData["msg"] = value; // } // return View(); //} /// /// /// /// public ActionResult Index() { // ⽅式⼀ //string value = $"controller={["controller"]},action={["action"]}"; // ⽅式⼆ string value = ""; foreach(var item in ) { value += $"{}={} "; } ViewData["msg"] = value; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }} 运⾏效果:因为是⼀个字典集合,所以可以遍历,这样⽆论URL⾥⾯有多少参数,都可以获取到对应的value值。6.3、action参数控制器代码:using System;using c;using ;using ;using ;namespace llers{ public class HomeController : Controller { /// /// tring /// /// //public ActionResult Index() //{ // if(tring["bookid"]!=null) // { // string value = tring["bookid"]; // ViewData["msg"] = value; // } // return View(); //} /// /// /// /// //public ActionResult Index() //{ // // ⽅式⼀ // //string value = $"controller={["controller"]},action={["action"]}"; // // ⽅式⼆ // string value = ""; // foreach(var item in ) // { // value += $"{}={} "; // } // ViewData["msg"] = value; // return View(); //} /// /// action参数 /// ⽅法参数名称必须和URL⾥⾯参数名称保持⼀致 /// /// public ActionResult Index(string controller,string action) { string value = $"controller={controller},action={action}"; ViewData["msg"] = value; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }}运⾏效果:7、由路由到URL解释说明:1. 1.由路由⽣成URL其实就是简单的两句代码,第⼀步就是使⽤RouteCollection对象的GetVirtualPath⽅法,通过该⽅法可以返回⼀个VirtualPahData对象,该类型表⽰有关路由和虚拟路径的信息,包含了两个重载的⽅法,区别是第⼆个⽅法可以指定路由项的名称,就是添加路由时,设置的路由键名,参数Values表达⽣成URL时设置的参数值,是⼀个字典类型。2. 1.得到VirtualPahData实例后,就可以通过他的VirtualPath属性值得到URL地址,它是⼀个字符串类型,从路由的这个功能可以看出,他是有双向功能的,不同于URL重写!看下⾯的案例:修改RouteConfig代码如下:using System;using c;using ;using ;using ;using g;namespace MVCRouteToUrl{ public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { Route("{resource}.axd/{*pathInfo}"); te( name: "Default2", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", id = al } ); // 默认路由匹配规则 te( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = al } ); } }}控制器代码如下:using System;using c;using ;using ;using ;using g;namespace llers{ public class HomeController : Controller { public ActionResult Index() { // 1.不使⽤路由名称的⽅式⽣成URL VirtualPathData vp= tualPath(null, new RouteValueDictionary(new { controller = "Home", action = "Index2", id = 4 })); string url = lPath; ViewData["msg"] = url; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }} 界⾯运⾏效果:在看下⾯⼀种⽅式:控制器代码:using System;using c;using ;using ;using ;using g;namespace llers{ public class HomeController : Controller { public ActionResult Index() { // 1.不使⽤路由名称的⽅式⽣成URL //VirtualPathData vp= tualPath(null, new RouteValueDictionary(new { controller = "Home", action = "Index2", id = 4 })); //string url = lPath; //ViewData["msg"] = url; // 2.根据路由名称⽣成URL // 因为controller和id有默认值,所以这⾥只指定action的值 VirtualPathData vp = tualPath(null, "Default2", new RouteValueDictionary(new { action = "Index5" })); string url = lPath; ViewData["msg"] = url; return View(); } public ActionResult About() { e = "Your application description page."; return View(); } public ActionResult Contact() { e = "Your contact page."; return View(); } }} 运⾏效果:
发布者:admin,转转请注明出处:http://www.yc00.com/news/1688419076a135598.html
评论列表(0条)