高分求解:asp.net mvc在请求管道中的请求过程.

zhuanshen712 2011-02-22 10:40:59
我的理解是这样的:
HttpApplication本身并不提供对Request的处理功能,而是通过在不同阶段触发不同的Event。
在HttpApplication的BuildSteps过程中,加入了HttpApplication的各个可供注册的事件;
对于普通的webForm.aspx来说,steps.Add(new HttpApplication.MapHandlerExecutionStep(app));这个步骤获得了context的handler,具体来说也就是每个页面的handler,而steps.Add(new HttpApplication.CallHandlerExecutionStep(app));则通过调用step的execute,调用了handler.ProcessRequest()执行了真正页面的处理.这里的handler就是每个页面.
上面的过程对于asp.net mvc来说应该也是适用的,不同的是,mvc的handler是mvchandler,它不是具体的页面,而是通过mvchandler的ProcessRequest创建控制器,再调用controller的Execute得到action,进而得到iview.
我觉得,普通webform和mvc所不同的就在于获取handler不同,而mvc利用UrlRoutingModule截获了请求通过HttpApplication的事件并更改了HttpContext,其实也就是通过更改handler来获取它所需要的mvchandler.

问题来了,我在看之前版本的的UrlRoutingModule时,代码是这样的:
***************************************************************************************
版本1:
public class UrlRoutingModule : IHttpModule
{
protected virtual void Init(HttpApplication application)
{
//这个是下面的代码段1
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
//这个是代码段2
application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
}
}


//代码段1
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");
}
}


//代码段2
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;
}
}


这个过程可以理解:
application.PostResolveRequestCache(代码段1)这个是MapHandlerExecutionStep(app)之前的事件,在这个事件中更改了httpcontext,并将handler(在此也就是mvchandler)赋值给了context.Items[_requestDataKey].
application.PostMapRequestHandler(代码段2)这个是MapHandlerExecutionStep(app))之后,且处于CallHandlerExecutionStep(app))之前的事件,也就是说,这个时间,是处于获得了handler之后,而在调用handler.processrequest之前的时间.通过代码,可以看到,它将预先()置于context.Items[_requestDataKey]中的数据取了出来,并更改了handler,从而得到mvchandler.
总结为:
1:在MapHandlerExecutionStep之前,更改httpcontext,并设置mvchandler
2:正常的调用MapHandlerExecutionStep获得handler
3:更改第二步的handler为mvchandler
4:调用CallHandlerExecutionStep,从而调用mvchandler.processrequest
**********************************************************************************************
不理解的来了....

版本2:(v4.0)
protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}


private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
HttpContextBase context = new HttpContextWrapper(((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(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() }));
}
if (httpHandler is UrlAuthFailureHandler)
{
if (!FormsAuthenticationModule.FormsAuthRequired)
{
throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
}
else
{
context.RemapHandler(httpHandler);
}
}
}
}


可以看到,PostResolveRequestCache 这个事件的注册还是有的,而没有了PostMapRequestHandler的注册,我在msdn上查看时,看到这个方法已过时,而reflector是这样:
[Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]
public virtual void PostMapRequestHandler(HttpContextBase context)
{
}
同样也是过期的方法.
所以我就不明白了,这个事件取消了,那么怎么得到的mvchandler呢?而之前,在这个事件中,更改了context的handler.那么没有了这个事件之后,怎么在调用handler的processrequest之前,将handler置为mvchandler呢?

我看到,在context.RemapHandler(httpHandler)中,有this._remapHandler = handler;而在获取handler的时候,也就是在MapHandlerExecutionStep中获得handler的时候,代码中有:
IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;
using (new ApplicationImpersonationContext())
{
if (handler != null)
{
return handler;
}
..............

这个里面也同样有得到RemapHandlerInstance 的代码,难道是它吗?
也就是说,过程难道是这样??
1:在MapHandlerExecutionStep之前,更改httpcontext,并设置mvchandler为context的某个属性[先这样说,不一定正确]
2:正常的调用MapHandlerExecutionStep,提取之前的context某个属性,从而获得mvchandler
[这一步,由于第2步得到的已经是mvchandler,所以这步没有了,也就是没有了注册PostMapRequestHandler的方法 3:更改第二步的handler为mvchandler]
4:调用CallHandlerExecutionStep,从而调用mvchandler.processrequest

===========================
版本2是4.0版本的dll,求解.我不明白版本2的mvchandler是如何得到的.
各位大侠,给个答案.最好是能给个有具体代码的过程.先谢谢了.
...全文
722 54 打赏 收藏 转发到动态 举报
写回复
用AI写文章
54 条回复
切换为时间正序
请发表友善的回复…
发表回复
翔如飞飞 2011-11-05
  • 打赏
  • 举报
回复
楼主其实已经找到答案了:
IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;
翔如飞飞 2011-11-05
  • 打赏
  • 举报
回复
我关注的问题和楼主的一样,目前我只是找到了这:
internal class PipelineStepManager : HttpApplication.StepManager
{
// Fields
private WaitCallback _resumeStepsWaitCallback;
private bool _validateInputCalled;
private bool _validatePathCalled;

// Methods
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
internal PipelineStepManager(HttpApplication app) : base(app)
{
}

internal override void BuildSteps(WaitCallback stepCallback)
{
HttpApplication app = base._application;
HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);
//此处省略

}
子夜__ 2011-02-23
  • 打赏
  • 举报
回复
低调的感觉 2011-02-23
  • 打赏
  • 举报
回复
zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
刚刚看了看application的MapHttpHandler,有很大的修改.可能是在这儿....
phil999 2011-02-23
  • 打赏
  • 举报
回复
没收到qq消息
zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
已加你qq.谢谢了....
kaizhilin 2011-02-23
  • 打赏
  • 举报
回复
好吧,让我动力十足
phil999 2011-02-23
  • 打赏
  • 举报
回复
楼主真是好学,私信发个QQ,交个朋友


HttpApplication+PipelineStepManager 类的 BuildSteps 函数

internal override void BuildSteps(WaitCallback stepCallback)
{
HttpApplication app = base._application;
HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);
HttpApplication.IExecutionStep step2 = new HttpApplication.CallHandlerExecutionStep(app);
app.AddEventMapping("ManagedPipelineHandler", RequestNotification.ExecuteRequestHandler, false, step2);
HttpApplication.IExecutionStep step3 = new HttpApplication.CallFilterExecutionStep(app);
app.AddEventMapping("AspNetFilterModule", RequestNotification.UpdateRequestCache, false, step3);
app.AddEventMapping("AspNetFilterModule", RequestNotification.LogRequest, false, step3);
this._resumeStepsWaitCallback = stepCallback;
}

zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 phil999 的回复:]

在 reflector 里找到 IExecutionStep,点 Derived Types,选 MaterializeHandlerExecutionStep
[/Quote]
果然正点,原来就是这个.
我查找了v2.0的dll,相比v4.0的dll,就少了这些:
if (httpContext.RemapHandlerInstance != null)
{
httpContext.Handler = httpContext.RemapHandlerInstance;
}
而这些,正好是UrlRouteModule里面存入的mvcHandler.怪不得v4.0版本的UrlRouteModule不用在CallHandlerExecutionStep之前注册PostMapRequestHandler事件去修改handler了呢...哈哈.
多谢兄弟了.

就是还有一个小问题比较遗憾,还不知道这个MaterializeHandlerExecutionStep是啥时候加入application的ExecuteSteps中的...
zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
不能说是啥时候执行的,是MaterializeHandlerExecutionStep是啥时候加入application的ExecuteSteps中的呢...
zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 phil999 的回复:]

在 reflector 里找到 IExecutionStep,点 Derived Types,选 MaterializeHandlerExecutionStep
[/Quote]
强啊兄弟,可是这个步骤MaterializeHandlerExecutionStep是啥时候执行的呢?
我得再找找....
phil999 2011-02-23
  • 打赏
  • 举报
回复
我查了一下,Materialize 的意思是:具体化;成为现实
phil999 2011-02-23
  • 打赏
  • 举报
回复
在 reflector 里找到 IExecutionStep,点 Derived Types,选 MaterializeHandlerExecutionStep
zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 phil999 的回复:]
if (httpContext.RemapHandlerInstance != null)
{
httpContext.Handler = httpContext.RemapHandlerInstance;
}
// 这里省略1万字

[/Quote]
有这样的代码?在哪儿啊?我看看...
我刚刚找了半天怎么没找到?
phil999 2011-02-23
  • 打赏
  • 举报
回复
context.RemapHandler(httpHandler) 之后,context.RemapHandlerInstance 就不为 null 了,这是另个函数,有一句是 httpContext.Handler = httpContext.RemapHandlerInstance;。种种迹象表明,application 会检查 context.RemapHandlerInstance 属性,如果它不为 null,他就是要用的 http handler



void HttpApplication.IExecutionStep.Execute()
{
HttpContext httpContext = this._application.Context;
HttpRequest request = httpContext.Request;
IHttpHandler handler = null;
string managedHandlerType = null;
if (EtwTrace.IsTraceEnabled(5, 1))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, httpContext.WorkerRequest);
}
IIS7WorkerRequest workerRequest = httpContext.WorkerRequest as IIS7WorkerRequest;
if (httpContext.RemapHandlerInstance != null)
{
httpContext.Handler = httpContext.RemapHandlerInstance;
}
// 这里省略1万字
}




zhuanshen712 2011-02-23
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 phil999 的回复:]

这句:
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);

和这句:
context.RemapHandler(httpHandler);
[/Quote]
兄弟谢谢了...
你看这个帖子问题的最下面我写的:

...
我看到,在context.RemapHandler(httpHandler)中,有this._remapHandler = handler;而在获取handler的时候,也就是在MapHandlerExecutionStep中获得handler的时候,代码中有:
IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;
using (new ApplicationImpersonationContext())
{
if (handler != null)
{
return handler;
}
..............

这个里面也同样有得到RemapHandlerInstance 的代码,难道是它吗?
也就是说,过程难道是这样??
1:在MapHandlerExecutionStep之前,更改httpcontext,并设置mvchandler为context的某个属性[先这样说,不一定正确]
2:正常的调用MapHandlerExecutionStep,提取之前的context某个属性,从而获得mvchandler
[这一步,由于第2步得到的已经是mvchandler,所以这步没有了,也就是没有了注册PostMapRequestHandler的方法 3:更改第二步的handler为mvchandler]
4:调用CallHandlerExecutionStep,从而调用mvchandler.processrequest


就是这里不明白啊....
phil999 2011-02-23
  • 打赏
  • 举报
回复
这个是 remap handler 的实现

public void RemapHandler(IHttpHandler handler)
{
IIS7WorkerRequest request = this._wr as IIS7WorkerRequest;
if (request != null)
{
if (this._notificationContext.CurrentNotification >= RequestNotification.MapRequestHandler)
{
throw new InvalidOperationException(SR.GetString("Invoke_before_pipeline_event", new object[] { "HttpContext.RemapHandler", "HttpApplication.MapRequestHandler" }));
}
string handlerType = null;
string handlerName = null;
if (handler != null)
{
Type type = handler.GetType();
handlerType = type.AssemblyQualifiedName;
handlerName = type.FullName;
}
request.SetRemapHandler(handlerType, handlerName);
}
this._remapHandler = handler;
}




phil999 2011-02-23
  • 打赏
  • 举报
回复
这句:
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);

和这句:
context.RemapHandler(httpHandler);
phil999 2011-02-23
  • 打赏
  • 举报
回复


protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}




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(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() }));
}
if (httpHandler is UrlAuthFailureHandler)
{
if (!FormsAuthenticationModule.FormsAuthRequired)
{
throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
}
else
{
context.RemapHandler(httpHandler);
}
}
}
}



加载更多回复(28)

110,925

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧