华域联盟 .Net Asp.net请求处理之管道处理介绍

Asp.net请求处理之管道处理介绍

在了解Asp.net请求处理流程的过程中,个人认为有必要从源代码的角度来了解asp.net管道是怎么实现的。

在此之前大家有必要了解一些asp.net请求流程的基本东东,如ASP.NET 请求处理流程、Asp.net管道、ASP.NET管线与应用程序生命周期

我们大家都知道HttpRuntime主要的方法是

public static void ProcessRequest(HttpWorkerRequest wr)

复制代码 代码如下:

private void ProcessRequestInternal(HttpWorkerRequest wr)

{

HttpContext context;

try

{

context = new HttpContext(wr, false);

}

catch

{

wr.SendStatus(400, "Bad Request");

wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");

byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");

wr.SendResponseFromMemory(bytes, bytes.Length);

wr.FlushResponse(true);

wr.EndOfRequest();

return;

}

wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);

Interlocked.Increment(ref this._activeRequestCount);

HostingEnvironment.IncrementBusyCount();

try

{

try

{

this.EnsureFirstRequestInit(context);

}

catch

{

if (!context.Request.IsDebuggingRequest)

{

throw;

}

}

context.Response.InitResponseWriter();

IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);

if (applicationInstance == null)

{

throw new HttpException(SR.GetString("Unable_create_app_object"));

}

if (EtwTrace.IsTraceEnabled(5, 1))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start");

}

if (applicationInstance is IHttpAsyncHandler)

{

IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;

context.AsyncAppHandler = handler2;

handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);

}

else

{

applicationInstance.ProcessRequest(context);

this.FinishRequest(context.WorkerRequest, context, null);

}

}

catch (Exception exception)

{

context.Response.InitResponseWriter();

this.FinishRequest(wr, context, exception);

}

}

我们看到里面有这么一句

IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);用来获取HttpApplication,而HttpApplication实现了IHttpAsyncHandler接口public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable,最后调用application的BeginProcessRequest方法。

HttpApplicationFactory.GetApplicationInstance(context)主要是调用GetNormalApplicationInstance

复制代码 代码如下:

internal static IHttpHandler GetApplicationInstance(HttpContext context)

{

if (_customApplication != null)

{

return _customApplication;

}

if (context.Request.IsDebuggingRequest)

{

return new HttpDebugHandler();

}

_theApplicationFactory.EnsureInited();

_theApplicationFactory.EnsureAppStartCalled(context);

return _theApplicationFactory.GetNormalApplicationInstance(context);

}

复制代码 代码如下:

private HttpApplication GetNormalApplicationInstance(HttpContext context)

{

HttpApplication application = null;

lock (this._freeList)

{

if (this._numFreeAppInstances > 0)

{

application = (HttpApplication) this._freeList.Pop();

this._numFreeAppInstances--;

if (this._numFreeAppInstances < this._minFreeAppInstances)

{

this._minFreeAppInstances = this._numFreeAppInstances;

}

}

}

if (application == null)

{

application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);

using (new ApplicationImpersonationContext())

{

application.InitInternal(context, this._state, this._eventHandlerMethods);

}

}

return application;

}

在GetNormalApplicationInstance里面有一个比较关键的方法application.InitInternal(context, this._state, this._eventHandlerMethods);我们猜测它是做Application初始化的工作,包括http管道的初始化。

复制代码 代码如下:

internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)

{

this._state = state;

PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);

try

{

try

{

this._initContext = context;

this._initContext.ApplicationInstance = this;

context.ConfigurationPath = context.Request.ApplicationPathObject;

using (new DisposableHttpContextWrapper(context))

{

if (HttpRuntime.UseIntegratedPipeline)

{

try

{

context.HideRequestResponse = true;

this._hideRequestResponse = true;

this.InitIntegratedModules();

goto Label_006B;

}

finally

{

context.HideRequestResponse = false;

this._hideRequestResponse = false;

}

}

this.InitModules();

Label_006B:

if (handlers != null)

{

this.HookupEventHandlersForApplicationAndModules(handlers);

}

this._context = context;

if (HttpRuntime.UseIntegratedPipeline && (this._context != null))

{

this._context.HideRequestResponse = true;

}

this._hideRequestResponse = true;

try

{

this.Init();

}

catch (Exception exception)

{

this.RecordError(exception);

}

}

if (HttpRuntime.UseIntegratedPipeline && (this._context != null))

{

this._context.HideRequestResponse = false;

}

this._hideRequestResponse = false;

this._context = null;

this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);

if (HttpRuntime.UseIntegratedPipeline)

{

this._stepManager = new PipelineStepManager(this);

}

else

{

this._stepManager = new ApplicationStepManager(this);

}

this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

}

finally

{

this._initInternalCompleted = true;

context.ConfigurationPath = null;

this._initContext.ApplicationInstance = null;

this._initContext = null;

}

}

catch

{

throw;

}

}

这个方法关键的代码在于:

复制代码 代码如下:

if (HttpRuntime.UseIntegratedPipeline)

{

this._stepManager = new PipelineStepManager(this);

}

else

{

this._stepManager = new ApplicationStepManager(this);

}

this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

我想大家看到这里就会明白为什么IIS7会有集成模式和经典模式了吧。可能大家不怎么重视此代码,让我们来看看经典模式的ApplicationStepManager

复制代码 代码如下:

internal class ApplicationStepManager : HttpApplication.StepManager

{

// Fields

private int _currentStepIndex;

private int _endRequestStepIndex;

private HttpApplication.IExecutionStep[] _execSteps;

private int _numStepCalls;

private int _numSyncStepCalls;

private WaitCallback _resumeStepsWaitCallback;

// Methods

internal ApplicationStepManager(HttpApplication app) : base(app)

{

}

internal override void BuildSteps(WaitCallback stepCallback)

{

ArrayList steps = new ArrayList();

HttpApplication app = base._application;

bool flag = false;

UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;

flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);

steps.Add(new HttpApplication.ValidateRequestExecutionStep(app));

steps.Add(new HttpApplication.ValidatePathExecutionStep(app));

if (flag)

{

steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));

}

app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);

app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);

app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);

app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);

app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);

steps.Add(new HttpApplication.MapHandlerExecutionStep(app));

app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);

app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);

steps.Add(new HttpApplication.CallHandlerExecutionStep(app));

app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);

app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);

steps.Add(new HttpApplication.CallFilterExecutionStep(app));

app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);

app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);

this._endRequestStepIndex = steps.Count;

app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);

steps.Add(new HttpApplication.NoopExecutionStep());

this._execSteps = new HttpApplication.IExecutionStep[steps.Count];

steps.CopyTo(this._execSteps);

this._resumeStepsWaitCallback = stepCallback;

}

internal override void InitRequest()

{

this._currentStepIndex = -1;

this._numStepCalls = 0;

this._numSyncStepCalls = 0;

base._requestCompleted = false;

}

[DebuggerStepperBoundary]
internal override void ResumeSteps(Exception error)

{

bool flag = false;

bool completedSynchronously = true;

HttpApplication application = base._application;

HttpContext context = application.Context;

HttpApplication.ThreadContext context2 = null;

AspNetSynchronizationContext syncContext = context.SyncContext;

lock (base._application)

{

try

{

context2 = application.OnThreadEnter();

}

catch (Exception exception)

{

if (error == null)

{

error = exception;

}

}

try

{

try

{

Label_0045:

if (syncContext.Error != null)

{

error = syncContext.Error;

syncContext.ClearError();

}

if (error != null)

{

application.RecordError(error);

error = null;

}

if (syncContext.PendingOperationsCount > 0)

{

syncContext.SetLastCompletionWorkItem(this._resumeStepsWaitCallback);

}

else

{

if ((this._currentStepIndex < this._endRequestStepIndex) && ((context.Error != null) || base._requestCompleted))

{

context.Response.FilterOutput();

this._currentStepIndex = this._endRequestStepIndex;

}

else

{

this._currentStepIndex++;

}

if (this._currentStepIndex >= this._execSteps.Length)

{

flag = true;

}

else

{

this._numStepCalls++;

context.SyncContext.Enable();

error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);

if (completedSynchronously)

{

this._numSyncStepCalls++;

goto Label_0045;

}

}

}

}

finally

{

if (context2 != null)

{

try

{

context2.Leave();

}

catch

{

}

}

}

}

catch

{

throw;

}

}

if (flag)

{

context.Unroot();

application.AsyncResult.Complete(this._numStepCalls == this._numSyncStepCalls, null, null);

application.ReleaseAppInstance();

}

}

}

说简单一点这个类中的internal override void BuildSteps(WaitCallback stepCallback)方法就是为我们注册那19个管道事件, internal override void ResumeSteps(Exception error)就是依次执行此管道事件,而 steps.Add(new HttpApplication.MapHandlerExecutionStep(app));是映射我们的handler

复制代码 代码如下:

internal class MapHandlerExecutionStep : HttpApplication.IExecutionStep

{

// Fields

private HttpApplication _application;

// Methods

internal MapHandlerExecutionStep(HttpApplication app)

{

this._application = app;

}

void HttpApplication.IExecutionStep.Execute()

{

HttpContext context = this._application.Context;

HttpRequest request = context.Request;

if (EtwTrace.IsTraceEnabled(5, 1))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, context.WorkerRequest);

}

context.Handler = this._application.MapHttpHandler(context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);

if (EtwTrace.IsTraceEnabled(5, 1))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_LEAVE, context.WorkerRequest);

}

}

// Properties

bool HttpApplication.IExecutionStep.CompletedSynchronously

{

get

{

return true;

}

}

bool HttpApplication.IExecutionStep.IsCancellable

{

get

{

return false;

}

}

}

里面的调用主要是

context.Handler = this._application.MapHttpHandler(context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);

而HttpApplication的MapHttpHandler如下:

复制代码 代码如下:

internal IHttpHandler MapHttpHandler(HttpContext context, string requestType, VirtualPath path, string pathTranslated, bool useAppConfig)

{

IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;

using (new ApplicationImpersonationContext())

{

if (handler != null)

{

return handler;

}

HttpHandlerAction mapping = this.GetHandlerMapping(context, requestType, path, useAppConfig);

if (mapping == null)

{

PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_FOUND);

PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED);

throw new HttpException(SR.GetString("Http_handler_not_found_for_request_type", new object[] { requestType }));

}

IHttpHandlerFactory factory = this.GetFactory(mapping);

try

{

IHttpHandlerFactory2 factory2 = factory as IHttpHandlerFactory2;

if (factory2 != null)

{

handler = factory2.GetHandler(context, requestType, path, pathTranslated);

}

else

{

handler = factory.GetHandler(context, requestType, path.VirtualPathString, pathTranslated);

}

}

catch (FileNotFoundException exception)

{

if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))

{

throw new HttpException(0x194, null, exception);

}

throw new HttpException(0x194, null);

}

catch (DirectoryNotFoundException exception2)

{

if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))

{

throw new HttpException(0x194, null, exception2);

}

throw new HttpException(0x194, null);

}

catch (PathTooLongException exception3)

{

if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))

{

throw new HttpException(0x19e, null, exception3);

}

throw new HttpException(0x19e, null);

}

if (this._handlerRecycleList == null)

{

this._handlerRecycleList = new ArrayList();

}

this._handlerRecycleList.Add(new HandlerWithFactory(handler, factory));

}

return handler;

}

在MapHttpHandler里创建了IHttpHandlerFactory,进而创建了httphandler。

在ApplicationStepManager中BuildSteps的方法有steps.Add(new HttpApplication.CallHandlerExecutionStep(app));这么一句,这就是注册调用我们hanndler的地方。

复制代码 代码如下:

internal class CallHandlerExecutionStep : HttpApplication.IExecutionStep

{

// Fields

private HttpApplication _application;

private AsyncCallback _completionCallback;

private IHttpAsyncHandler _handler;

private bool _sync;

// Methods

internal CallHandlerExecutionStep(HttpApplication app)

{

this._application = app;

this._completionCallback = new AsyncCallback(this.OnAsyncHandlerCompletion);

}

private void OnAsyncHandlerCompletion(IAsyncResult ar)

{

if (!ar.CompletedSynchronously)

{

HttpContext context = this._application.Context;

Exception error = null;

try

{

try

{

this._handler.EndProcessRequest(ar);

}

finally

{

context.Response.GenerateResponseHeadersForHandler();

}

}

catch (Exception exception2)

{

if ((exception2 is ThreadAbortException) || ((exception2.InnerException != null) && (exception2.InnerException is ThreadAbortException)))

{

this._application.CompleteRequest();

}

else

{

error = exception2;

}

}

if (EtwTrace.IsTraceEnabled(4, 4))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);

}

this._handler = null;

context.SetStartTime();

if (HttpRuntime.IsLegacyCas)

{

this.ResumeStepsWithAssert(error);

}

else

{

this.ResumeSteps(error);

}

}

}

private void ResumeSteps(Exception error)

{

this._application.ResumeStepsFromThreadPoolThread(error);

}

[PermissionSet(SecurityAction.Assert, Unrestricted=true)]
private void ResumeStepsWithAssert(Exception error)

{

this.ResumeSteps(error);

}

void HttpApplication.IExecutionStep.Execute()

{

HttpContext context = this._application.Context;

IHttpHandler handler = context.Handler;

if (EtwTrace.IsTraceEnabled(4, 4))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_ENTER, context.WorkerRequest);

}

if ((handler != null) && HttpRuntime.UseIntegratedPipeline)

{

IIS7WorkerRequest workerRequest = context.WorkerRequest as IIS7WorkerRequest;

if ((workerRequest != null) && workerRequest.IsHandlerExecutionDenied())

{

this._sync = true;

HttpException exception = new HttpException(0x193, SR.GetString("Handler_access_denied"));

exception.SetFormatter(new PageForbiddenErrorFormatter(context.Request.Path, SR.GetString("Handler_access_denied")));

throw exception;

}

}

if (handler == null)

{

this._sync = true;

}

else if (handler is IHttpAsyncHandler)

{

IHttpAsyncHandler handler2 = (IHttpAsyncHandler) handler;

this._sync = false;

this._handler = handler2;

IAsyncResult result = handler2.BeginProcessRequest(context, this._completionCallback, null);

if (result.CompletedSynchronously)

{

this._sync = true;

this._handler = null;

try

{

handler2.EndProcessRequest(result);

}

finally

{

context.Response.GenerateResponseHeadersForHandler();

}

if (EtwTrace.IsTraceEnabled(4, 4))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);

}

}

}

else

{

this._sync = true;

context.SyncContext.SetSyncCaller();

try

{

handler.ProcessRequest(context);

}

finally

{

context.SyncContext.ResetSyncCaller();

if (EtwTrace.IsTraceEnabled(4, 4))

{

EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);

}

context.Response.GenerateResponseHeadersForHandler();

}

}

}

// Properties

bool HttpApplication.IExecutionStep.CompletedSynchronously

{

get

{

return this._sync;

}

}

bool HttpApplication.IExecutionStep.IsCancellable

{

get

{

return !(this._application.Context.Handler is IHttpAsyncHandler);

}

}

}

在代码中我们看到handler2.BeginProcessRequest(context, this._completionCallback, null);。。。handler.ProcessRequest(context);这2句代码是不是很熟悉啊。

在让我们回头看看HttpApplication的BeginProcessRequest方法

复制代码 代码如下:

IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

{

this._context = context;

this._context.ApplicationInstance = this;

this._stepManager.InitRequest();

this._context.Root();

HttpAsyncResult result = new HttpAsyncResult(cb, extraData);

this.AsyncResult = result;

if (this._context.TraceIsEnabled)

{

HttpRuntime.Profile.StartRequest(this._context);

}

this.ResumeSteps(null);

return result;

}

里面调用了ResumeSteps方法

复制代码 代码如下:

private void ResumeSteps(Exception error)

{

this._stepManager.ResumeSteps(error);

}

回到我们先前的ApplicationStepManager的ResumeSteps方法,里面有一句

error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);

Ahhpaplication的ExecuteStep方法

复制代码 代码如下:

internal Exception ExecuteStep(IExecutionStep step, ref bool completedSynchronously)

{

Exception exception = null;

try

{

try

{

if (step.IsCancellable)

{

this._context.BeginCancellablePeriod();

try

{

step.Execute();

}

finally

{

this._context.EndCancellablePeriod();

}

this._context.WaitForExceptionIfCancelled();

}

else

{

step.Execute();

}

if (!step.CompletedSynchronously)

{

completedSynchronously = false;

return null;

}

}

catch (Exception exception2)

{

exception = exception2;

if (ImpersonationContext.CurrentThreadTokenExists)

{

exception2.Data["ASPIMPERSONATING"] = string.Empty;

}

if ((exception2 is ThreadAbortException) && ((Thread.CurrentThread.ThreadState & ThreadState.AbortRequested) == ThreadState.Running))

{

exception = null;

this._stepManager.CompleteRequest();

}

}

catch

{

}

}

catch (ThreadAbortException exception3)

{

if ((exception3.ExceptionState != null) && (exception3.ExceptionState is CancelModuleException))

{

CancelModuleException exceptionState = (CancelModuleException) exception3.ExceptionState;

if (exceptionState.Timeout)

{

exception = new HttpException(SR.GetString("Request_timed_out"), null, 0xbb9);

PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TIMED_OUT);

}

else

{

exception = null;

this._stepManager.CompleteRequest();

}

Thread.ResetAbort();

}

}

completedSynchronously = true;

return exception;

}

是真正执行IExecutionStep的Execute方法。

通过以上的分析我们可以简单的理解asp.net在管道模式下管道主要是通过ApplicationStepManager来注册和调用的。集成模式下的PipelineStepManager和ApplicationStepManager结构类似。

个人在这里只是抛砖引玉,希望大家拍砖。

您可能感兴趣的文章:

  • Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码
  • ASP.NET Core 3.0 gRPC拦截器的使用
  • asp.net mvc core管道及拦截器的理解

本文由 华域联盟 原创撰写:华域联盟 » Asp.net请求处理之管道处理介绍

转载请保留出处和原文链接:https://www.cnhackhy.com/44548.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部