在了解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結構類似。
個人在這裡只是拋磚引玉,希望大家拍磚。