從前面篇章的解析, 其實能看的出來, IHttpModule 可以注冊很多個, 而且可以從web.config注冊, 可以動態注冊. 但是有一個關鍵性的Module沒有講, 這裡就先來講一下這個關鍵性的Module -- UrlRoutingModule
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class UrlRoutingModule : IHttpModule
{
// Fields
private static readonly object _contextKey;
private static readonly object _requestDataKey;
private RouteCollection _routeCollection;
// Methods
static UrlRoutingModule();
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public UrlRoutingModule();
protected virtual void Dispose();
protected virtual void Init(HttpApplication application);
private void OnApplicationPostResolveRequestCache(object sender, EventArgs e);
[Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]
public virtual void PostMapRequestHandler(HttpContextBase context);
public virtual void PostResolveRequestCache(HttpContextBase context);
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
void IHttpModule.Dispose();
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
void IHttpModule.Init(HttpApplication application);
// Properties
public RouteCollection RouteCollection { get; [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set; }
}
來看一下他的Init方法, 注冊了什麼進去.
protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}
從上一篇的那個事件圖上可以看到, 這個是注冊在緩存檢查結束的事件上. 在看這個注冊的方法之前, 還需要講點別的. 因為在執行這個方法之前, 先執行的 Application_Start方法, 在這個方法中, 我們創建了路由表. 並在路由表中加入了匹配的路由規則.
那先來講一下路由注冊吧.
一、路由注冊
路由注冊這裡, 分為一般理由注冊,區域路由注冊,api路由注冊. 這裡只介紹一般路由注冊, 其實是一樣的, 只是注冊的匹配規則不同而已.
在Application_Start方法中, 路由注冊就是下面這句話了.
RouteConfig.RegisterRoutes(RouteTable.Routes);
先來看一下, 這個方法的參數.
// 摘要:
// 存儲應用程序的 URL 路由。
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0,
Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class RouteTable
{
// 摘要:
// 初始化 System.Web.Routing.RouteTable 類的新實例。
public RouteTable();
// 摘要:
// 獲取從 System.Web.Routing.RouteBase 類派生的對象的集合。
//
// 返回結果:
// 包含集合中的所有路由的對象。
public static RouteCollection Routes { get; }
}
從這裡能看到, 其實他傳的是一個靜態路由集合, 封裝成了一個路由表.
接下來就進入這個方法來看一下.
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 },
constraints: new { controller=@"^\w+$", id=@"^\d+$" } //可以不寫, 這裡是對名稱和參數的約束
);
}
這裡的IgnoreRoute就不看了, 直接看MapRoute方法, 這個方法是存放在靜態擴展類中的: RouteCollectionExtensions
裡面有很多的重載, 我只看那個參數最多的方法吧.
public static Route MapRoute(this RouteCollection routes, string name, string url,
object defaults, object constraints, string[] namespaces) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } Route item = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { item.DataTokens["Namespaces"] = namespaces; } routes.Add(name, item); return item; }
這裡就是解析參數, 並創建路由存入路由集合中, 即存入路由表中.
1. 這裡出現了一個 MvcRouteHandler的東東, 名字感覺跟MVC有點關系了, 那進去瞧瞧?
public class MvcRouteHandler : IRouteHandler
{
// Fields
private IControllerFactory _controllerFactory;
// Methods
public MvcRouteHandler();
public MvcRouteHandler(IControllerFactory controllerFactory);
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext);
protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext);
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext);
}
這個GetHttpHandler裡面, 有讓人激動的東東哦, 先看一下吧, 不繼續講解了
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
return new MvcHandler(requestContext);
}
2. 這裡為啥defaults和 constraints 都存成 CreateRouteValueDictionary 類型呢, 這裡暫時只看一下他存放到哪裡吧.
private static RouteValueDictionary CreateRouteValueDictionary(object values)
{
IDictionary<string, object> dictionary = values as IDictionary<string, object>;
if (dictionary != null)
{
return new RouteValueDictionary(dictionary);
}
return new RouteValueDictionary(values);
}
public RouteValueDictionary(object values)
{
this._dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
this.AddValues(values);
}
從這裡看, defaults, constraints , DataTokens 都是相同的類型.
等後面要用的時候, 再去解析吧.
這一篇算是與MVC掛上鉤了, 下一篇就正式進入MVC環節的解析.
目錄已同步