在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
MVC 通过在 web.config 中添加相应的 Module 来参与 ASP.NET 执行流程。 <httpModules>
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing ..." /> </httpModules> 那么,这个 UrlRoutingModule 自然就是我们分析过程的入口。 public class UrlRoutingModule : IHttpModule
{ protected virtual void Init(HttpApplication application) { application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler); } } 订阅了两个 HttpApplication 事件~~~~ 嗯,PostResolveRequestCache 要比 PostMapRequestHandler 更早执行,先从它开始吧。 private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{ HttpContextBase context = new HttpContextWrapper2(((HttpApplication) sender).Context); this.PostResolveRequestCache(context); } public virtual void PostResolveRequestCache(HttpContextBase context) { RouteData routeData = this.RouteCollection.GetRouteData(context); if (routeData != null) { IRouteHandler routeHandler = routeData.RouteHandler; if (routeHandler == null) { throw new InvalidOperationException(...); } RequestContext requestContext = new RequestContext(context, routeData); IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); if (httpHandler == null) { throw new InvalidOperationException(...); } context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler }; context.RewritePath("~/UrlRouting.axd"); } } 首先从 RouteCollection 中获取一个 RouteData 对象,RouteCollection 何许人也? public RouteCollection RouteCollection
{ get { if (this._routeCollection == null) { this._routeCollection = RouteTable.Routes; } return this._routeCollection; } set { this._routeCollection = value; } } 说白了,所谓 RouteCollection 就是我们在 Global.asax.cs 中添加的 Route 集合。 public static void RegisterRoutes(RouteCollection routes)
{ // Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable // automatic support on IIS6 and IIS7 classic mode routes.Add(new Route("{controller}/{action}/{id}", new MvcRouteHandler()) { Defaults = new RouteValueDictionary(new { action = "Index", id = "" }), }); routes.Add(new Route("Default.aspx", new MvcRouteHandler()) { Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }), }); } 回到上文,在获取 RoteCollection 之后,通过调用 GetRouteData(context) 返回一个 RouteData 对象(详细代码可阅读 Route.GetRouteData 方法,它通过分析当前上下文的相关请求参数,返回所需的结果对象),该对象内部包含了我们注册 Route 时的相关设置,当然就有下面所需要的 —— MvcRouteHandler。 接下来,该方法将 routeData 和上下文一起打包成 RequestContext,这应该是给后面相关处理准备的上下文环境。通过调用 MvcRouteHandler.GetHttpHandler() 方法,我们终于看到了曙光,也就是进行后续流程的关键 —— MvcHandler (有关 MvcHandler 的细节,后续章节再说)。 public class MvcRouteHandler : IRouteHandler
{ protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { return new MvcHandler(requestContext); } } 到了这一步,MVC 框架已经准备好了相应的执行场景,接下来就是修改默认的执行流程了。当然,辛苦得来的 "环境" 要选择一个合适的 "人",存储到一个合适的 "地方"。 context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };
而后的某个时间,OnApplicationPostMapRequestHandler 被执行。在 PostMapRequestHandler 中,它提取了前面预先 "埋" 下的 "坏蛋",并修改了 HttpContext.Handler,使得 MvcHandler 能继续未完的 "事业"。至于跳转之类的,就无需我再多说。 private void OnApplicationPostMapRequestHandler(object sender, EventArgs e)
{ HttpContextBase context = new HttpContextWrapper2(((HttpApplication) sender).Context); this.PostMapRequestHandler(context); } public virtual void PostMapRequestHandler(HttpContextBase context) { RequestData data = (RequestData) context.Items[_requestDataKey]; if (data != null) { context.RewritePath(data.OriginalPath); context.Handler = data.HttpHandler; } } 待续…… ---------------------------- 附上流程分析图 查看大图 |
请发表评论