ASP.NET MVC Preview 2 - 流程分析 (1)
2008-04-30 13:17 Jacky_Xu 阅读(519) 评论(0) 编辑 收藏 举报
很早就想写来着,尤其是用 MVC Preview 1 做过一个项目以后。不过,依照微软以往的习惯,Beta2 之前的每个版本之间都有很大的差异,本文有多少生命周期,也很难说。不废话,开始正文……
MVC 通过在 web.config 中添加相应的 Module 来参与 ASP.NET 执行流程。
那么,这个 UrlRoutingModule 自然就是我们分析过程的入口。
订阅了两个 HttpApplication 事件~~~~ 嗯,PostResolveRequestCache 要比 PostMapRequestHandler 更早执行,先从它开始吧。
首先从 RouteCollection 中获取一个 RouteData 对象,RouteCollection 何许人也?
说白了,所谓 RouteCollection 就是我们在 Global.asax.cs 中添加的 Route 集合。
回到上文,在获取 RoteCollection 之后,通过调用 GetRouteData(context) 返回一个 RouteData 对象(详细代码可阅读 Route.GetRouteData 方法,它通过分析当前上下文的相关请求参数,返回所需的结果对象),该对象内部包含了我们注册 Route 时的相关设置,当然就有下面所需要的 —— MvcRouteHandler。
接下来,该方法将 routeData 和上下文一起打包成 RequestContext,这应该是给后面相关处理准备的上下文环境。通过调用 MvcRouteHandler.GetHttpHandler() 方法,我们终于看到了曙光,也就是进行后续流程的关键 —— MvcHandler (有关 MvcHandler 的细节,后续章节再说)。
到了这一步,MVC 框架已经准备好了相应的执行场景,接下来就是修改默认的执行流程了。当然,辛苦得来的 "环境" 要选择一个合适的 "人",存储到一个合适的 "地方"。
而后的某个时间,OnApplicationPostMapRequestHandler 被执行。在 PostMapRequestHandler 中,它提取了前面预先 "埋" 下的 "坏蛋",并修改了 HttpContext.Handler,使得 MvcHandler 能继续未完的 "事业"。至于跳转之类的,就无需我再多说。
待续……
----------------------------
附上流程分析图
查看大图
MVC 通过在 web.config 中添加相应的 Module 来参与 ASP.NET 执行流程。
<httpModules>
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing ..." />
</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);
}
}
{
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");
}
}
{
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;
}
}
{
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 = "" }),
});
}
{
// 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);
}
}
{
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;
}
}
{
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;
}
}
待续……
----------------------------
附上流程分析图
查看大图