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结构类似。

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