MVC路由解析---IgnoreRoute
文章引导
Area--->AreaRegister.RegisterAllArea()与Area区域的解析(一)
引言
Reflector源码反编译工具软件是必备
一.由路由注册开始
严格的说Route不只属于MVC,MVC所有的请求都是通过路由规则去映射的,所以MVC的头等大事就是路由规则的注册。规则的注册时在Global.asax的Application_Start事件里注册,以下是默认的路由注册代码
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 7 routes.MapRoute( 8 name: "Default", 9 url: "{controller}/{action}/{id}", 10 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 11 ); 12 } 13 }
我们这篇文章的讲述内容以routes.IgnoreRoute("{resource}.axd/{*pathInfo}")深入学习
二.Application_Start的传参
IgnoreRoute的方法参数传入是由Application_Start的RouteConfig.RegisterRoutes(RouteTable.Routes)传入。但是RouteConfig类中RegisterRoutes的参数却为RouteCollection,好吧,我们的工作开始了。我们先来看RouteTable有什么深处含义。
RouteTable源码:
1 private static RouteCollection _instance; 2 static RouteTable() 3 { 4 _instance = new RouteCollection(); 5 } 6 7 public static RouteCollection Routes 8 { 9 get { return _instance; } 10 }
RouteTable是一个单例模式(如果不知道这个模式的同学可以去学习一下设计模式),Routes是一个公共的静态属性,属性的类型是RouteCollection。这也是RouteConfig类中的RegisterRoutes的参数为RouteCollection的缘故。
总结:RouteTable只有一个职责,就是构建一个静态单例RouteCollection,RouteCollection是一个泛型类:Collection<RouteBase>。这个RouteCollection用来保存路由规则的集合。
三.RouteCollection的IgnoreRoute
废话不多说,上源码(这个时候就是Reflection的厉害之处了):
public class RouteCollection:Collection<RouteBase> { private Dictionary<string, RouteBase> _namedMap; private ReaderWriterLock _rwLock; public RouteCollection() { _namedMap = new Dictionary<string, RouteBase>(StringComparer.OrdinalIgnoreCase); _rwLock = new ReaderWriterLock(); } public void Ignore(string url) { Ignore(url, null); } public void Ignore(string url,object constraints) { if (url == null) { throw new ArgumentNullException("url"); } IgnoreRouteInternal item = new IgnoreRouteInternal(url) { Constraints=new System.Web.Routing.RouteValueDictionary(constraints) }; base.Add(item); } }
上源码中RouteCollection是一个泛型继承了RouteBase的集合类Collection。
四.IgnoreRouteInternal
为了更好的深入了解,我们继续深入下去,现在看下IgnoreRouteInternal:
public sealed class IgnoreRouteInternal:Route { public IgnoreRouteInternal(string url):base(url,new StopRoutingHandler()) { } }
可以看到,这是一个密封类,是不允许被继承的,但他却继承了Route,Route class是继承了RouteBase class。IgnoreRouteInternal有参构造函数调用的是Route的有参构造函数。
五.StopRoutingHandler
我们先来拆开StopRoutingHandler 看一下:
public class StopRoutingHandler:System.Web.Routing.IRouteHandler { IHttpHandler System.Web.Routing.IRouteHandler.GetHttpHandler(System.Web.Routing.RequestContext requestContext) { return this.GetHttpHandler(requestContext); } protected virtual IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext req) { throw new NotSupportedException(); } }
StopRoutingHandler是个特殊的RouteHandler对象,它的作用只是告诉UrlRouteModule,虽然某个规则匹配成功了,但是也还是当什么没有发生,说白了,我们需要去忽略一些规则。
我们来看一下一个如何被忽略的例子,阻止路由处理.axd文件的请求。
routes.Add(new Route("{resource}/.axd/{*pathInfo}",new StopRoutingHandler()));
六.IRouteHandler
打打鸡血,我们继续来拆解IRouteHandler
// // 摘要: // 定义类必须实现才能处理匹配路由模式的请求的协定。 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] public interface IRouteHandler { // // 摘要: // 提供处理请求的对象。 // // 参数: // requestContext: // 一个对象,封装有关请求的信息。 // // 返回结果: // 一个处理请求的对象。 IHttpHandler GetHttpHandler(RequestContext requestContext);
IRouteHandler接口方法GetHttpHandler必须返回一个实现了IHttpHandler的信息,接受的参数类型为RequestContext,看到这个RequestContext,大家就会眼前一亮。这个是一个非常重要的点。
此处引入一位大神的Blog内容:深入解析路由系统架构原理 ----->https://www.cnblogs.com/Leo_wl/p/3380570.html
七.Route
我们回到第四步,public IgnoreRouteInternal(string url):base(url,new StopRoutingHandler())我们来看看Route的构造函数
public class Route:RouteBase { private string _url; public System.Web.Routing.IRouteHandler RouteHandler { get; set; } public Route(string url,System.Web.Routing.IRouteHandler routeHandler) { this._url = url; RouteHandler = routeHandler; } public System.Web.Routing.RouteValueDictionary Constraints { get; set; } }
八.base.Add(item)
RouteCollection是一个集合类,默认集合,将IgnoreRouteInternal放入集合。
思维导图:
System.Web.dll文件反编译后的源码:System.Web.dll