嚴格的說Route不只屬于MVC,MVC所有的請求都是通過路由規則去映射的,所以MVC的頭等大事就是路由規則的注冊。規則的注冊時在Global.asax的Application_Start事件里注冊,以下是默認的路由注冊代碼
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
我們這篇文章的講述內容以routes.IgnoreRoute("{resource}.axd/{*pathInfo}")深入學習
IgnoreRoute的方法參數傳入是由Application_Start的RouteConfig.RegisterRoutes(RouteTable.Routes)傳入。但是RouteConfig類中RegisterRoutes的參數卻為RouteCollection,好吧,我們的工作開始了。我們先來看RouteTable有什么深處含義。
RouteTable源碼:
private static RouteCollection _instance; static RouteTable() { _instance = new RouteCollection(); } public static RouteCollection Routes { get { return _instance; } }
RouteTable是一個單例模式(如果不知道這個模式的同學可以去學習一下設計模式),Routes是一個公共的靜態屬性,屬性的類型是RouteCollection。這也是RouteConfig類中的RegisterRoutes的參數為RouteCollection的緣故。
廢話不多說,上源碼(這個時候就是Reflection的厲害之處了):
public class RouteCollection:Collection上源碼中RouteCollection是一個泛型繼承了RouteBase的集合類Collection。{ private Dictionary _namedMap; private ReaderWriterLock _rwLock; public RouteCollection() { _namedMap = new Dictionary (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); } }
為了更好的深入了解,我們繼續深入下去,現在看下IgnoreRouteInternal:
public sealed class IgnoreRouteInternal:Route { public IgnoreRouteInternal(string url):base(url,new StopRoutingHandler()) { } }可以看到,這是一個密封類,是不允許被繼承的,但他卻繼承了Route,Route class是繼承了RouteBase class。IgnoreRouteInternal有參構造函數調用的是Route的有參構造函數。
我們先來拆開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
// // 摘要: // 定義類必須實現才能處理匹配路由模式的請求的協定。 [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,大家就會眼前一亮。這個是一個非常重要的點。
我們回到第四步,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; } }
RouteCollection是一個集合類,默認集合,將IgnoreRouteInternal放入集合。
思維導圖: