分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

.Net MVC5路由机制与扩展

发布时间:2023-09-06 02:01责任编辑:赖小花关键词:MVC

新建一个MVC项目启动后,首先访问的地址是http://localhost:xxx/Home/Index,这时候我们也明白因为在程序中有个叫做Home的控制器,并且在这个控制器下面有个叫做Index的方法,基于这种对应的关系,才有了这种结果,那么这种对应关系是如何产生,如何工作的了?

在我们网站在第一次启动的时候,会去访问一个全局的配置文件Global.asax下面的Application_Start()方法,代码如下

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Optimization; 7 using System.Web.Routing; 8 ?9 namespace Test10 {11 ????public class MvcApplication : System.Web.HttpApplication12 ????{13 ????????protected void Application_Start()14 ????????{15 ????????????AreaRegistration.RegisterAllAreas();16 ????????????FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);17 ????????????RouteConfig.RegisterRoutes(RouteTable.Routes);18 ????????????BundleConfig.RegisterBundles(BundleTable.Bundles);19 ????????}20 ????}21 }

在这个方法中就注册了我们的路由配置,相关的注册文件都是在在App_Data目录下

 路由配置文件RouteConfig.cs,内容如下

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 ?8 namespace Test 9 {10 ????public class RouteConfig11 ????{12 ????????public static void RegisterRoutes(RouteCollection routes)13 ????????{14 ????????????routes.IgnoreRoute("{resource}.axd/{*pathInfo}");15 16 ????????????routes.MapRoute(17 ????????????????name: "Default",18 ????????????????url: "{controller}/{action}/{id}",19 ????????????????defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }20 ????????????);21 ????????}22 ????}23 }

首先是忽略路由,满足匹配会被忽略,如果没有特殊需求,这个地方就不需要更改,

name表示路由的名称,同一个路由集合中,路由名称必须唯一,不能够有重名,

url就是正则表达式,用于http://localhost:xxx/后路径地址的匹配,

defaults表示缺省路由,也就是默认的路由.这是一个路由规则增删的方法,并且默认的路由为home/index,

还有一个比较常用的参数是constraints,用于条件约束,简单实例如下:

 1 ????public class RouteConfig 2 ????{ 3 ????????public static void RegisterRoutes(RouteCollection routes) 4 ????????{ 5 ????????????routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 ?7 ????????????//假若Home下有Test(int year,int month,int day)方法 8 ????????????//home/Test_2017_06_05可以访问至该方法 9 ????????????//home/Test_2017_6_05是无法访问10 ????????????routes.MapRoute(11 ??????????????name: "Constraints",12 ??????????????url: "{controller}/{action}_{year}_{month}_{day}",13 ??????????????defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },14 ??????????????//条件参数,约束后面参数(此处简单正则:4位数字,2位数字,2位数字)15 ??????????????constraints: new { year = @"^\d{4}", month = @"^\d{2}", day = @"^\d{2}" });16 17 ????????????routes.MapRoute(18 ????????????????name: "Default",19 ????????????????url: "{controller}/{action}/{id}",20 ????????????????defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });21 ????????}22 ????}

路由浅析

那么路由究竟是如何工作的,下面是2个与路由工作十分紧密的2个方法的源码,任何http请求进入后,都会先被它们处理

 1 public virtual void PostResolveRequestCache(HttpContextBase context) 2 ????{ 3 ????????RouteData routeData = RouteCollection.GetRouteData(context); 4 ????????if (routeData != null) 5 ????????{ 6 ????????????IRouteHandler routeHandler = routeData.RouteHandler; 7 ????????????if (routeHandler == null) 8 ????????????{ 9 ????????????????throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler")));10 ????????????}11 ????????????if (!(routeHandler is StopRoutingHandler))12 ????????????{13 ????????????????RequestContext requestContext = new RequestContext(context, routeData);14 ????????????????context.Request.RequestContext = requestContext;15 ????????????????IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);16 ????????????????if (httpHandler == null)17 ????????????????{18 ????????????????????throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[1]19 ????????????????????{20 ????????????????????????routeHandler.GetType()21 ????????????????????}));22 ????????????????}23 ????????????????if (httpHandler is UrlAuthFailureHandler)24 ????????????????{25 ????????????????????if (FormsAuthenticationModule.FormsAuthRequired)26 ????????????????????{27 ????????????????????????UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);28 ????????????????????????return;29 ????????????????????}30 ????????????????????throw new HttpException(401, SR.GetString("Assess_Denied_Description3"));31 ????????????????}32 ????????????????context.RemapHandler(httpHandler);33 ????????????}34 ????????}35 ????}
PostResolveRequestCache
 1 public RouteData GetRouteData(HttpContextBase httpContext) 2 { 3 ????if (httpContext == null) 4 ????{ 5 ????????throw new ArgumentNullException("httpContext"); 6 ????} 7 ????if (httpContext.Request == null) 8 ????{ 9 ????????throw new ArgumentException(SR.GetString("RouteTable_ContextMissingRequest"), "httpContext");10 ????}11 ????if (base.Count == 0)12 ????{13 ????????return null;14 ????}15 ????bool flag = false;16 ????bool flag2 = false;17 ????if (!RouteExistingFiles)18 ????{19 ????????flag = IsRouteToExistingFile(httpContext);20 ????????flag2 = true;21 ????????if (flag)22 ????????{23 ????????????return null;24 ????????}25 ????}26 ????using (GetReadLock())27 ????{28 ????????foreach (RouteBase item in this)29 ????????{30 ????????????RouteData routeData = item.GetRouteData(httpContext);31 ????????????if (routeData != null)32 ????????????{33 ????????????????if (!item.RouteExistingFiles)34 ????????????????{35 ????????????????????if (!flag2)36 ????????????????????{37 ????????????????????????flag = IsRouteToExistingFile(httpContext);38 ????????????????????????flag2 = true;39 ????????????????????}40 ????????????????????if (flag)41 ????????????????????{42 ????????????????????????return null;43 ????????????????????}44 ????????????????}45 ????????????????return routeData;46 ????????????}47 ????????}48 ????}49 ????return null;50 }
GetRouteData

大致分析下这段源码,我们可以得出下列比较重要的结论

1在路由匹配之前,先一步检查了物理文件的存在,所以mvc和webform可以共存,如果存在满足路径条件的aspx文件,它会优先被访问

2路由是从上到下逐个匹配的,所以排列的顺序对于路由匹配是非常重要的

 路由扩展

在上述基础下,我们对路由有了大概的了解,对此我们可以简单扩展一下

路由并不是只能够在路径规则上做文章,我们也可以继承路由的基类RouteBase自定义一些路由,然后把自定义的路由放入注册路由集合中,调准好顺序,实现我们想要的结果.因为能够得到HttpContext这个用户请求的上下文,我们可以完成很多扩展,例如检查ip,浏览器类型,参数等等,下面我们就简单的实现不同浏览器访问到不同路径的功能,如下:

 1 ????public class RouteConfig 2 ????{ 3 ????????public static void RegisterRoutes(RouteCollection routes) 4 ????????{ 5 ????????????routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 ?7 ????????????//注意顺序 8 ????????????routes.Add("Agent",new Agent()); 9 10 ????????????routes.MapRoute(11 ????????????????name: "Default",12 ????????????????url: "{controller}/{action}/{id}",13 ????????????????defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });14 ????????}15 16 ??????17 ????}18 ????public class Agent : RouteBase19 ????{20 ????????public override RouteData GetRouteData(HttpContextBase httpContext)21 ????????{22 ????????????if (httpContext.Request.UserAgent.Contains("Chrome/63.0.3239.132"))23 ????????????{24 ????????????????var data = new RouteData(this, new MvcRouteHandler());25 ????????????????data.Values.Add("controller", "Home");26 ????????????????data.Values.Add("action", "About");27 ????????????????return data;28 ????????????}29 ????????????else30 ????????????{31 ????????????????return null;32 ????????????}33 ????????}34 35 ????????public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)36 ????????{37 ????????????return null;38 ????????}39 ????}

一定得注意路由排列的顺序,如果将上面的Agent路由放在Default路由后面,那么就直接会访问到Home/Index,而不会去判断.

我们也可以通过自定义继承了RouteBase的Route类,来完成特殊路径的扩展,如下

 1 ??public class RouteConfig 2 ????{ 3 ????????public static void RegisterRoutes(RouteCollection routes) 4 ????????{ 5 ????????????routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 ?7 ????????????routes.Add(new Route("Test",new TestRouteHandler())); 8 ?9 ????????????routes.MapRoute(10 ????????????????name: "Default",11 ????????????????url: "{controller}/{action}/{id}",12 ????????????????defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });13 ????????}14 ????}15 16 ????public class TestRouteHandler : IRouteHandler17 ????{18 ????????public IHttpHandler GetHttpHandler(RequestContext requestContext)19 ????????{20 ????????????return new TestHandler();21 ????????}22 ????}23 ????public class TestHandler : IHttpHandler24 ????{25 ????????public bool IsReusable => true;26 27 ????????public void ProcessRequest(HttpContext context)28 ????????{29 ????????????context.Response.Write("Test");30 ????????}31 ????}

效果如下:

出自:博客园-半路独行

 原文地址:https://www.cnblogs.com/banluduxing/p/9185159.html

 本文出自于http://www.cnblogs.com/banluduxing 转载请注明出处。

.Net MVC5路由机制与扩展

原文地址:https://www.cnblogs.com/banluduxing/p/9185159.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved