国内最大设计网站,8小8x人2022成免费入口,jsp网站开发详解 赵增敏,网站项目开发流程本章节主要讲IIS和 管道内部如何处理客户端Http请求#xff0c;会较多的以代码的形式讲述#xff0c;让大家对HttpApplication、HttpHandler、HttpApplicationFactory、Page这几个在处理请求过程中扮演重要角色的对象有更深入的了解。
下面我们通过单步调式跟踪System.Web.D…本章节主要讲IIS和 管道内部如何处理客户端Http请求会较多的以代码的形式讲述让大家对HttpApplication、HttpHandler、HttpApplicationFactory、Page这几个在处理请求过程中扮演重要角色的对象有更深入的了解。
下面我们通过单步调式跟踪System.Web.Dll源码来分析各个过程中关键处理函数
说明部分代码只保留了关键代码
1、首先进入管道运行时中的托管入口函数
IIS集成模式
在IPipelineRuntime.cs类中请求通知函数ProcessRequestNotification并调用ProcessRequestNotificationHelper函数 internal static int ProcessRequestNotification( IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, int flags) { try { //调用ProcessRequestNotificationHelper return ProcessRequestNotificationHelper(rootedObjectsPointer, nativeRequestContext, moduleData, flags); } catch(Exception e) { ApplicationManager.RecordFatalException(e); throw; } }
2、在ProcessRequestNotificationHelper函数中调用运行时HttpRuntime中的ProcessRequestNotification函数
internal static int ProcessRequestNotificationHelper( IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, int flags) { IIS7WorkerRequest wr null; HttpContext context null; RequestNotificationStatus status RequestNotificationStatus.Continue; RootedObjects root; bool workerRequestWasJustCreated false; try { status HttpRuntime.ProcessRequestNotification(wr, context);//调用ProcessRequestNotification函数 } finally { } return (int)status; } 3、在ProcessRequestNotification中调用ProcessRequestNotificationPrivate
4、处理请求通知ProcessRequestNotificationPrivate函数中调用了HttpApplicatioinFactory的GetApplicationInstance()函数来获取HttpApplication实例对象并调用BeginProcessRequestNotification处理请求 private RequestNotificationStatus ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) { RequestNotificationStatus status RequestNotificationStatus.Pending; try { IHttpHandler handler null; if (context.NeedToInitializeApp()) { try { EnsureFirstRequestInit(context); } catch { } context.Response.InitResponseWriter(); handler HttpApplicationFactory.GetApplicationInstance(context);//获取HttpApplication实例 if (handler null) throw new HttpException(SR.GetString(SR.Unable_create_app_object)); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, handler.GetType().FullName, Start); HttpApplication app handler as HttpApplication; if (app ! null) { // associate the context with an application instance app.AssignContext(context); } } wr.SynchronizeVariables(context); if (context.ApplicationInstance ! null) { // 处理请求 IAsyncResult ar context.ApplicationInstance.BeginProcessRequestNotification(context, _requestNotificationCompletionCallback); if { status RequestNotificationStatus.Continue; } } else if (handler ! null) { // HttpDebugHandler is processed here handler.ProcessRequest(context); status RequestNotificationStatus.FinishRequest; } else { status RequestNotificationStatus.Continue; } } catch (Exception e) { } return status; }
IIS经典模式
在ISAPIRuntime.cs类中请求 ProcessRequest函数并调用HttpRuntime.ProcessReques方法
1、HttpRuntime处理请求入口函数 public static void ProcessRequest(HttpWorkerRequest wr) { if (wr null) throw new ArgumentNullException(wr); if (HttpRuntime.UseIntegratedPipeline) { throw new PlatformNotSupportedException(SR.GetString(SR.Method_Not_Supported_By_Iis_Integrated_Mode, HttpRuntime.ProcessRequest)); } ProcessRequestNoDemand(wr);//调用ProcessRequestNoDemand函数 } 2、ProcessRequestNoDemand函数调用ProcessRequestNow函数 internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) { RequestQueue rq _theRuntime._requestQueue; wr.UpdateInitialCounters(); if (rq ! null) // could be null before first request wr rq.GetRequestToExecute(wr); if (wr ! null) { CalculateWaitTimeAndUpdatePerfCounter(wr); wr.ResetStartTime(); ProcessRequestNow(wr);调用ProcessRequestNow } } 3、ProcessRequestNow函数调用ProcessRequestInternal internal static void ProcessRequestNow(HttpWorkerRequest wr) { _theRuntime.ProcessRequestInternal(wr);//调用ProcessRequestInternal }
4、ProcessRequestInternal函数调用HttpApplicatioinFactory的GetApplicationInstance()函数来获取HttpApplication实例对象 private void ProcessRequestInternal(HttpWorkerRequest wr) { // Count active requests Interlocked.Increment(ref _activeRequestCount); // Get application instance IHttpHandler app HttpApplicationFactory.GetApplicationInstance(context);//获取HttpApplication对象 if (app null) throw new HttpException(SR.GetString(SR.Unable_create_app_object)); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, app.GetType().FullName, Start); if (app is IHttpAsyncHandler) { // asynchronous handler IHttpAsyncHandler asyncHandler (IHttpAsyncHandler)app; context.AsyncAppHandler asyncHandler; //来到了真正处理请求步骤 asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context); } else { // synchronous handler app.ProcessRequest(context); FinishRequest(context.WorkerRequest, context, null); } } catch (Exception e) { context.Response.InitResponseWriter(); FinishRequest(wr, context, e); } }
说明以上4个步骤集成模式和经典模式分不同的函数执行从下面开始两种模式调用相同的函数只是在函数中针对不同的模式进行不同的处理
5、进入HttpApplicationFactory调用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);//返回HttpApplication实例 }
6、进入GetNormalApplicationInstance函数调用InitInternal初始化HttpApplication内部对象 private HttpApplication GetNormalApplicationInstance(HttpContext context) { HttpApplication app null; lock (_freeList) { if (_numFreeAppInstances 0) { app (HttpApplication)_freeList.Pop(); _numFreeAppInstances--; if (_numFreeAppInstances _minFreeAppInstances) { _minFreeAppInstances _numFreeAppInstances; } } } if (app null) { // If ran out of instances, create a new one app (HttpApplication)HttpRuntime.CreateNonPublicInstance(_theApplicationType); using (new ApplicationImpersonationContext()) { app.InitInternal(context, _state, _eventHandlerMethods);//初始化Application内部对象 } } if (AppSettings.UseTaskFriendlySynchronizationContext) { // When this HttpApplication instance is no longer in use, recycle it. app.ApplicationInstanceConsumersCounter new CountdownTask(1); // representing required call to HttpApplication.ReleaseAppInstance app.ApplicationInstanceConsumersCounter.Task.ContinueWith((_, o) RecycleApplicationInstance((HttpApplication)o), app, TaskContinuationOptions.ExecuteSynchronously); } return app; }
7、进入HttpApplication,调用InitInternal函数来初始化Application内部对象。初始化HttpModule和建立处理执行步骤
internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) { Debug.Assert(context ! null, context ! null); // Remember state _state state; PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES); try { try { // Remember context for config lookups _initContext context; _initContext.ApplicationInstance this; // Set config path to be application path for the application initialization context.ConfigurationPath context.Request.ApplicationPathObject; // keep HttpContext.Current working while running user code using (new DisposableHttpContextWrapper(context)) { // Build module list from config 根据IIS集成模式和经典模式初始化HttpMudule if (HttpRuntime.UseIntegratedPipeline) { //集成模式 Debug.Assert(_moduleConfigInfo ! null, _moduleConfigInfo ! null); Debug.Assert(_moduleConfigInfo.Count 0, _moduleConfigInfo.Count 0); try { context.HideRequestResponse true; _hideRequestResponse true; InitIntegratedModules();//集成模式初始化HttpModule } finally { context.HideRequestResponse false; _hideRequestResponse false; } } else { //经典模式 InitModules();//经典模式初始化HttpModule // this is used exclusively for integrated mode Debug.Assert(null _moduleContainers, null _moduleContainers); } // Hookup event handlers via reflection if (handlers ! null) HookupEventHandlersForApplicationAndModules(handlers); // Initialization of the derived class _context context; if (HttpRuntime.UseIntegratedPipeline _context ! null) { _context.HideRequestResponse true; } _hideRequestResponse true; try { Init(); } catch (Exception e) { RecordError(e); } } if (HttpRuntime.UseIntegratedPipeline _context ! null) { _context.HideRequestResponse false; } _hideRequestResponse false; _context null; _resumeStepsWaitCallback new WaitCallback(this.ResumeStepsWaitCallback); // Construct the execution steps array span stylecolor:#FF0000;strongif (HttpRuntime.UseIntegratedPipeline) {/strong/span //集成模式 调用PipelineStepManager span stylecolor:#FF0000;strong_stepManager new PipelineStepManager(this);/strong/span } else { span stylecolor:#FF0000;strong _stepManager new ApplicationStepManager(this);/strong/span //经典模式 调用 ApplicationStepManager } span stylecolor:#FF0000;strong_stepManager.BuildSteps(_resumeStepsWaitCallback);/strong/span //建立执行处理步骤 } finally { _initInternalCompleted true; // Reset config path context.ConfigurationPath null; // dont hold on to the context _initContext.ApplicationInstance null; _initContext null; } } catch { // Protect against exception filters throw; } }
8、初始化HttpModule包含系统默认的HttpModule和自定义的HttpModule
1、系统默认的HttpModule
C:\Windows\\Framework64\v4.0.30319\Config\web.config 2、自定义的HttpModule在网站的Web.config中配置
经典模式
system.web httpModules add namemymodule typeWebApplication2.myModule/ /httpModules /system.web 集成模式 system.webServer modules add namemymodule typeWebApplication2.myModule/ /modules /system.webServer 3、经典模式初始化 private void InitModules() { //读取配置文件中HttpModules节点 HttpModulesSection pconfig RuntimeConfig.GetAppConfig().HttpModules; //获取HttpModule集合 HttpModuleCollection moduleCollection pconfig.CreateModules(); HttpModuleCollection dynamicModules CreateDynamicModules(); moduleCollection.AppendCollection(dynamicModules); _moduleCollection moduleCollection; // dont assign until all ops have succeeded InitModulesCommon();//调用InitModulesCommon }
4、初始化各个HttpModule对象. private void InitModulesCommon() { int n _moduleCollection.Count; for (int i 0; i n; i) { // remember the module being inited for event subscriptions // well later use this for routing _currentModuleCollectionKey _moduleCollection.GetKey(i); _moduleCollection[i].Init(this);//初始化每个HttpModule } _currentModuleCollectionKey null; InitAppLevelCulture(); }
5、初始化HttpModule在Init函数中注册HttpApplication对象的事件这里举了两个例子
OutputCacheModule.cs web.config中默认第一个HttpModule void IHttpModule.Init(HttpApplication app) { OutputCacheSection cacheConfig RuntimeConfig.GetAppConfig().OutputCache; if (cacheConfig.EnableOutputCache) { app.ResolveRequestCache new EventHandler(this.OnEnter); app.UpdateRequestCache new EventHandler(this.OnLeave); } } SessionStateModule.cs web.config中默认第二个HttpModule实现Session的系统HttpModule public void Init(HttpApplication app) { bool initModuleCalled false; SessionStateSection config RuntimeConfig.GetAppConfig().SessionState; if (!s_oneTimeInit) { s_lock.AcquireWriterLock(); try { if (!s_oneTimeInit) { InitModuleFromConfig(app, config); initModuleCalled true; if (!CheckTrustLevel(config)) s_trustLevelInsufficient true; s_timeout (int)config.Timeout.TotalMinutes; s_useHostingIdentity config.UseHostingIdentity; // See if we can try InProc optimization. See inline doc of s_allowInProcOptimization // for details. if (config.Mode SessionStateMode.InProc _usingAspnetSessionIdManager) { s_allowInProcOptimization true; } if (config.Mode ! SessionStateMode.Custom config.Mode ! SessionStateMode.Off !config.RegenerateExpiredSessionId) { s_allowDelayedStateStoreItemCreation true; } s_configExecutionTimeout RuntimeConfig.GetConfig().HttpRuntime.ExecutionTimeout; s_configRegenerateExpiredSessionId config.RegenerateExpiredSessionId; s_configCookieless config.Cookieless; s_configMode config.Mode; // The last thing to set in this if-block. s_oneTimeInit true; Debug.Trace(SessionStateModuleInit, Configuration: _mode config.Mode ;Timeout config.Timeout ;CookieMode config.Cookieless ;SqlConnectionString config.SqlConnectionString ;StateConnectionString config.StateConnectionString ;s_allowInProcOptimization s_allowInProcOptimization ;s_allowDelayedStateStoreItemCreation s_allowDelayedStateStoreItemCreation); } } finally { s_lock.ReleaseWriterLock(); } } if (!initModuleCalled) { InitModuleFromConfig(app, config); } if (s_trustLevelInsufficient) { throw new HttpException(SR.GetString(SR.Session_state_need_higher_trust)); } }
集成模式初始化HttpModule代码我就不贴出来了大家可以在源码中查看
9、建立处理步骤BuildSteps将所有要执行的步骤载入到一个IExecutionStep[]集合中待后面ResumeSteps调用
经典模式调用ApplicationStepManager类中的BuildSteps函数
internal class ApplicationStepManager : StepManager { private IExecutionStep[] _execSteps; private WaitCallback _resumeStepsWaitCallback; private int _currentStepIndex; private int _numStepCalls; private int _numSyncStepCalls; private int _endRequestStepIndex; internal ApplicationStepManager(HttpApplication app): base(app) { } internal override void BuildSteps(WaitCallback stepCallback ) { ArrayList steps new ArrayList(); HttpApplication app _application; bool urlMappingsEnabled false; UrlMappingsSection urlMappings RuntimeConfig.GetConfig().UrlMappings; urlMappingsEnabled urlMappings.IsEnabled ( urlMappings.UrlMappings.Count 0 ); steps.Add(new ValidateRequestExecutionStep(app)); steps.Add(new ValidatePathExecutionStep(app)); if (urlMappingsEnabled) steps.Add(new UrlMappingsExecutionStep(app)); // url mappings 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 MapHandlerExecutionStep(app));//分配一个Handler app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps); app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps); steps.Add(app.CreateImplicitAsyncPreloadExecutionStep()); // implict async preload step steps.Add(new CallHandlerExecutionStep(app)); // 执行HttpHandler app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps); app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps); steps.Add(new CallFilterExecutionStep(app)); // filtering app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps); _endRequestStepIndex steps.Count; app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps); steps.Add(new NoopExecutionStep()); // the last is always there _execSteps new IExecutionStep[steps.Count]; steps.CopyTo(_execSteps); // callback for async completion when reposting to threadpool thread _resumeStepsWaitCallback stepCallback; }
集成模式调用PipelineStepManager类中的 BuildSteps函数 internal override void BuildSteps(WaitCallback stepCallback) { Debug.Trace(PipelineRuntime, BuildSteps); //ArrayList steps new ArrayList(); HttpApplication app _application; // add special steps that dont currently // correspond to a configured handler IExecutionStep materializeStep new MaterializeHandlerExecutionStep(app); // implicit map step app.AddEventMapping( HttpApplication.IMPLICIT_HANDLER, RequestNotification.MapRequestHandler, false, materializeStep); // implicit async preload step app.AddEventMapping( HttpApplication.IMPLICIT_HANDLER, RequestNotification.ExecuteRequestHandler, false, app.CreateImplicitAsyncPreloadExecutionStep()); // implicit handler routing step IExecutionStep handlerStep new CallHandlerExecutionStep(app); app.AddEventMapping( HttpApplication.IMPLICIT_HANDLER, RequestNotification.ExecuteRequestHandler, false, handlerStep); // implicit handler WebSockets step IExecutionStep webSocketsStep new TransitionToWebSocketsExecutionStep(app); app.AddEventMapping( HttpApplication.IMPLICIT_HANDLER, RequestNotification.EndRequest, true /* isPostNotification */, webSocketsStep); // add implicit request filtering step IExecutionStep filterStep new CallFilterExecutionStep(app); // normally, this executes during UpdateRequestCache as a high priority module app.AddEventMapping( HttpApplication.IMPLICIT_FILTER_MODULE, RequestNotification.UpdateRequestCache, false, filterStep); // for error conditions, this executes during LogRequest as a high priority module app.AddEventMapping( HttpApplication.IMPLICIT_FILTER_MODULE, RequestNotification.LogRequest, false, filterStep); _resumeStepsWaitCallback stepCallback; } 10、真正处理请求阶段 调用ResumeSteps函数来执行处理步骤
经典模式
返回到ProcessRequestInternal函数中执行BeginProcessRequest函数 IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) { HttpAsyncResult result; // Setup the asynchronous stuff and application variables _context context; _context.ApplicationInstance this; _stepManager.InitRequest(); // Make sure the context stays rooted (including all async operations) _context.Root(); // Create the async result result new HttpAsyncResult(cb, extraData); // Remember the async result for use in async completions AsyncResult result; if (_context.TraceIsEnabled) HttpRuntime.Profile.StartRequest(_context); // Start the application ResumeSteps(null);//执行处理步骤 // Return the async result return result; } ResumeSteps函数调用ExecuteStepl函数来执行处理步骤 internal override void ResumeSteps(Exception error) { bool appCompleted false; bool stepCompletedSynchronously true; HttpApplication app _application; CountdownTask appInstanceConsumersCounter app.ApplicationInstanceConsumersCounter; HttpContext context app.Context; ThreadContext threadContext null; AspNetSynchronizationContextBase syncContext context.SyncContext; Debug.Trace(Async, HttpApplication.ResumeSteps); try { if (appInstanceConsumersCounter ! null) { appInstanceConsumersCounter.MarkOperationPending(); // ResumeSteps call started } using (syncContext.AcquireThreadLock()) { //执行步骤 error app.ExecuteStep(_execSteps[_currentStepIndex], ref stepCompletedSynchronously); } }
集成模式
返回到ProcessRequestNotificationPrivate函数执行BeginProcessRequestNotification
BeginProcessRequestNotification函数调用ResumeSteps执行处理步骤
internal IAsyncResult BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) { if (this._context null) { this.AssignContext(context); } context.CurrentModuleEventIndex -1; HttpAsyncResult result new HttpAsyncResult(cb, context); context.NotificationContext.AsyncResult result; this.ResumeSteps(null);//开始执行处理步骤 return result; } ResumeSteps
// PipelineStepManager::ResumeSteps // called from IIS7 (on IIS thread) via BeginProcessRequestNotification // or from an async completion (on CLR thread) via HttpApplication::ResumeStepsFromThreadPoolThread // This attribute prevents undesirable just-my-code debugging behavior (VSWhidbey 404406/VSWhidbey 609188) [System.Diagnostics.DebuggerStepperBoundaryAttribute] internal override void ResumeSteps(Exception error) { HttpContext context _application.Context; IIS7WorkerRequest wr context.WorkerRequest as IIS7WorkerRequest; AspNetSynchronizationContextBase syncContext context.SyncContext; RequestNotificationStatus status RequestNotificationStatus.Continue; ThreadContext threadContext null; bool needToDisassociateThreadContext false; bool isSynchronousCompletion false; bool needToComplete false; bool stepCompletedSynchronously false; int currentModuleLastEventIndex _application.CurrentModuleContainer.GetEventCount(context.CurrentNotification, context.IsPostNotification) - 1; CountdownTask appInstanceConsumersCounter _application.ApplicationInstanceConsumersCounter; using (context.RootedObjects.WithinTraceBlock()) { error _application.ExecuteStep(step, ref stepCompletedSynchronously);//执行处理步骤 } } 11、ExecuteStep执行BuildSteps中的各个步骤 internal Exception ExecuteStep(IExecutionStep step, ref bool completedSynchronously) { Exception error null; try { try { if (step.IsCancellable) { _context.BeginCancellablePeriod(); // request can be cancelled from this point try { step.Execute(); } finally { _context.EndCancellablePeriod(); // request can be cancelled until this point } _context.WaitForExceptionIfCancelled(); // wait outside of finally } else { step.Execute();/strong/span } if { completedSynchronously false; return null; } } }
这里贴出了两个很重要的步骤获取HttpHandlerMaterializeHandlerExecutionStep和执行HttpHandlerCallHandlerExecutionStep
经典模式
MapHandlerExecutionStep
// execution step -- map HTTP handler (used to be a separate module) internal class span stylecolor:#FF0000;strongMapHandlerExecutionStep /strong/span: IExecutionStep { private HttpApplication _application; internal MapHandlerExecutionStep(HttpApplication app) { _application app; } void IExecutionStep.Execute() { HttpContext context _application.Context; HttpRequest request context.Request; if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, context.WorkerRequest); //获取HttpHandler context.Handler _application.MapHttpHandler( context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false /*useAppConfig*/);/strong/span Debug.Assert(context.ConfigurationPath context.Request.FilePathObject, context.ConfigurationPath ( context.ConfigurationPath ) ! context.Request.FilePath ( context.Request.FilePath )); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_LEAVE, context.WorkerRequest); } bool pletedSynchronously { get { return true;} } bool IExecutionStep.IsCancellable { get { return false; } } }
MapHttpHandler获取处理请求的HttpHandler
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);//获取HttpHandlerFactory对象如果网站Web.config中自定义了HttpHandlerFactory对象则会覆盖系统默认的 try { IHttpHandlerFactory2 factory2 factory as IHttpHandlerFactory2; if (factory2 ! null) { handler factory2.GetHandler(context, requestType, path, pathTranslated);//获取HttpHandler对象如果为自定义的HttpHandlerFactory则返回自定义HttpHandlerFactory中设置的HttpHandler } 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; }
集成模式
MaterializeHandlerExecutionStep步骤
internal class MaterializeHandlerExecutionStep: IExecutionStep { private HttpApplication _application; internal MaterializeHandlerExecutionStep(HttpApplication app) { _application app; } void IExecutionStep.Execute() { HttpContext context _application.Context; HttpRequest request context.Request; IHttpHandler handler null; string configType null; if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, context.WorkerRequest); IIS7WorkerRequest wr context.WorkerRequest as IIS7WorkerRequest; // Get handler if (context.RemapHandlerInstance ! null){ //RemapHandler overrides all wr.SetScriptMapForRemapHandler(); context.Handler context.RemapHandlerInstance; } else if (request.RewrittenUrl ! null) { // RewritePath, we need to re-map the handler bool handlerExists; configType wr.ReMapHandlerAndGetHandlerTypeString(context, request.Path, out handlerExists); if (!handlerExists) { // WOS 1973590: When RewritePath is used with missing handler in Integrated Mode,an empty response 200 is returned instead of 404 throw new HttpException(404, SR.GetString(SR.Http_handler_not_found_for_request_type, request.RequestType)); } } else { configType wr.GetManagedHandlerType(); } if (!String.IsNullOrEmpty(configType)) { IHttpHandlerFactory factory _application.GetFactory(configType);//获取HttpHandlerFactory对象 string pathTranslated request.PhysicalPathInternal; try { handler factory.GetHandler(context, request.RequestType, request.FilePath, pathTranslated);//获取HttpHandler对象 } catch (FileNotFoundException e) { if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated)) throw new HttpException(404, null, e); else throw new HttpException(404, null); } catch (DirectoryNotFoundException e) { if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated)) throw new HttpException(404, null, e); else throw new HttpException(404, null); } catch (PathTooLongException e) { if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated)) throw new HttpException(414, null, e); else throw new HttpException(414, null); } context.Handler handler; // Remember for recycling if (_application._handlerRecycleList null) _application._handlerRecycleList new ArrayList(); _application._handlerRecycleList.Add(new HandlerWithFactory(handler, factory)); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_LEAVE, context.WorkerRequest); } bool pletedSynchronously { get { return true;} } bool IExecutionStep.IsCancellable { get { return false; } } }
12、执行callhandlerexecutestep步骤调用handler.ProcessRequest(context)如果HttpHandler类型为Page则开始Page页生命周期
internal class CallHandlerExecutionStep: IExecutionStep { private HttpApplication _application; private AsyncCallback _completionCallback; private IHttpAsyncHandler _handler; // per call private AsyncStepCompletionInfo _asyncStepCompletionInfo; // per call private bool _sync; // per call internal CallHandlerExecutionStep(HttpApplication app) { _application app; _completionCallback new AsyncCallback(this.OnAsyncHandlerCompletion); } voidIExecutionStep.Execute() { HttpContext context _application.Context; IHttpHandler handler context.Handler; if (EtwTrace.IsTraceEnabled(rmation, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_ENTER, context.WorkerRequest); if (handler ! null HttpRuntime.UseIntegratedPipeline) { IIS7WorkerRequest wr context.WorkerRequest as IIS7WorkerRequest; if (wr ! null wr.IsHandlerExecutionDenied()) { _sync true; HttpException error new HttpException(403, SR.GetString(SR.Handler_access_denied)); error.SetFormatter(new PageForbiddenErrorFormatter(context.Request.Path, SR.GetString(SR.Handler_access_denied))); throw error; } } if (handler null) { _sync true; } else if (handler is IHttpAsyncHandler) { // asynchronous handler IHttpAsyncHandler asyncHandler (IHttpAsyncHandler)handler; _sync false; _handler asyncHandler; var beginProcessRequestDelegate AppVerifier.WrapBeginMethodHttpContext(_application, asyncHandler.BeginProcessRequest); _asyncStepCompletionInfo.Reset(); context.SyncContext.AllowVoidAsyncOperations(); IAsyncResult ar; try { ar beginProcessRequestDelegate(context, _completionCallback, null); } catch { // The asynchronous step has completed, so we should disallow further // async operations until the next step. context.SyncContext.ProhibitVoidAsyncOperations(); throw; } bool operationCompleted; bool mustCallEndHandler; _asyncStepCompletionInfo.RegisterBeginUnwound(ar, out operationCompleted, out mustCallEndHandler); if (operationCompleted) { _sync true; _handler null; // not to remember // The asynchronous step has completed, so we should disallow further // async operations until the next step. context.SyncContext.ProhibitVoidAsyncOperations(); try { if (mustCallEndHandler) { asyncHandler.EndProcessRequest(ar); } _asyncStepCompletionInfo.ReportError(); } finally { SuppressPostEndRequestIfNecessary(context); // In Integrated mode, generate the necessary response headers // after the handler runs context.Response.GenerateResponseHeadersForHandler(); } if (EtwTrace.IsTraceEnabled(rmation, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest); } } else { //同步 handler _sync true; context.SyncContext.SetSyncCaller(); try { handler.ProcessRequest(context);//开始Page页面生命周期 } finally { context.SyncContext.ResetSyncCaller(); if (EtwTrace.IsTraceEnabled(rmation, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest); SuppressPostEndRequestIfNecessary(context); context.Response.GenerateResponseHeadersForHandler(); } } } bool pletedSynchronously { get { return _sync;} } bool IExecutionStep.IsCancellable { // launching of async handler should not be cancellable get { return (_application.Context.Handler is IHttpAsyncHandler) ? false : true; } } }
13、进入Page类的 ProcessRequest方法开始处理请求 private void ProcessRequest() { // culture needs to be saved/restored only on synchronous pages (if at all) // save culture Thread currentThread Thread.CurrentThread; CultureInfo prevCulture currentThread.CurrentCulture; CultureInfo prevUICulture currentThread.CurrentUICulture; try { ProcessRequest(true /*includeStagesBeforeAsyncPoint*/, true /*includeStagesAfterAsyncPoint*/);//调用ProcessRequest函数 } finally { // restore culture RestoreCultures(currentThread, prevCulture, prevUICulture); } }
14、进入ProcessRequest,调用ProcessRequestMain函数
private void ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) { // Initialize the object and build the tree of controls. // This must happen *after* the intrinsics have been set. // On async pages only call Initialize once (ProcessRequest is called twice) if (includeStagesBeforeAsyncPoint) { FrameworkInitialize(); this.ControlState ControlState.FrameworkInitialized; } bool needToCallEndTrace Context.WorkerRequest is IIS7WorkerRequest; try { try { if (IsTransacted) { ProcessRequestTransacted(); } else { // No transactions ProcessRequestMain(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint);//调用ProcessRequestMain函数 } if (includeStagesAfterAsyncPoint) { needToCallEndTrace false; ProcessRequestEndTrace(); } } catch (ThreadAbortException) { try { if (needToCallEndTrace) ProcessRequestEndTrace(); } catch {} } finally { if (includeStagesAfterAsyncPoint) { ProcessRequestCleanup(); } } } catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835) }
15、进入ProcessRequestMain,开始Page页面主体处理过程
private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) { try { HttpContext con Context; string exportedWebPartID null; if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin PreInit); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_ENTER, _context.WorkerRequest); PerformPreInit(); //Page页面生命周期的OnPerLoad阶段 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End PreInit); if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin Init); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_ENTER, _context.WorkerRequest); InitRecursive(null); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End Init); if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin InitComplete); OnInitComplete(EventArgs.Empty);//Page页面生命周期的OnInitComplete阶段 if (con.TraceIsEnabled) Trace.Write(aspx.page, End InitComplete); if (IsPostBack) { if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin LoadState); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_ENTER, _context.WorkerRequest); LoadAllState();//Page页面生命周期的LoadViewState阶段加载视图状态 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) { Trace.Write(aspx.page, End LoadState); Trace.Write(aspx.page, Begin ProcessPostData); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_ENTER, _context.WorkerRequest); ProcessPostData(_requestValueCollection, true /* fBeforeLoad */);//Page页面生命周期ProcessPostData阶段处理回发数据 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End ProcessPostData); } if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin PreLoad); OnPreLoad(EventArgs.Empty);//Page页面生命周期OnPreLoad阶段预加载 if (con.TraceIsEnabled) Trace.Write(aspx.page, End PreLoad); if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin Load); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_ENTER, _context.WorkerRequest); LoadRecursive();//Page页面生命周期Load阶段加载 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End Load); if (IsPostBack) { // Try process the post data again (ASURT 29045) if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin ProcessPostData Second Try); span stylecolor:#FF0000;strong ProcessPostData(_leftoverPostData, false /* !fBeforeLoad */);//Page页面生命周期 ProcessPostData阶段/strong/span if (con.TraceIsEnabled) { Trace.Write(aspx.page, End ProcessPostData Second Try); Trace.Write(aspx.page, Begin Raise ChangedEvents); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_ENTER, _context.WorkerRequest); RaiseChangedEvents();//Page页面生命周期 RaiseChangedEvents阶段处理回发更改事件 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) { Trace.Write(aspx.page, End Raise ChangedEvents); Trace.Write(aspx.page, Begin Raise PostBackEvent); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_ENTER, _context.WorkerRequest); RaisePostBackEvent(_requestValueCollection);//Page页面生命周期 RaisePostBackEvent阶段处理回发事件 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End Raise PostBackEvent); } if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin LoadComplete); OnLoadComplete(EventArgs.Empty);//Page页面生命周期 加载完成 if (con.TraceIsEnabled) Trace.Write(aspx.page, End LoadComplete); if (IsPostBack IsCallback) { PrepareCallback(callbackControlId);//Page页面生命周期 PrepareRender(预呈现) } else if (!IsCrossPagePostBack) { if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin PreRender); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_ENTER, _context.WorkerRequest); PreRenderRecursiveInternal(); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End PreRender); } } /// Async Point here if (_legacyAsyncInfo null || _legacyAsyncInfo.CallerIsBlocking) { // for non-async pages with registered async tasks - run the tasks here // also when running async page via server.execute - run the tasks here ExecuteRegisteredAsyncTasks(); } // Make sure RawUrl gets validated. ValidateRawUrlIfRequired(); if (includeStagesAfterAsyncPoint) { if (IsCallback) { RenderCallback(); return; } if (IsCrossPagePostBack) { return; } if (con.TraceIsEnabled) Trace.Write(aspx.page, Begin PreRenderComplete); PerformPreRenderComplete(); if (con.TraceIsEnabled) Trace.Write(aspx.page, End PreRenderComplete); if (con.TraceIsEnabled) { BuildPageProfileTree(EnableViewState); Trace.Write(aspx.page, Begin SaveState); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_ENTER, _context.WorkerRequest); SaveAllState();//Page页面生命周期 SaveAllState阶段保存视图状态 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) { Trace.Write(aspx.page, End SaveState); Trace.Write(aspx.page, Begin SaveStateComplete); } OnSaveStateComplete(EventArgs.Empty); if (con.TraceIsEnabled) { Trace.Write(aspx.page, End SaveStateComplete); Trace.Write(aspx.page, Begin Render); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_ENTER, _context.WorkerRequest); // Special-case Web Part Export so it executes in the same security context as the page itself (VSWhidbey 426574) if (exportedWebPartID ! null) { ExportWebPart(exportedWebPartID); } else { RenderControl(CreateHtmlTextWriter(Response.Output));//Page页面生命周期 Render阶段呈现 } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_LEAVE, _context.WorkerRequest); if (con.TraceIsEnabled) Trace.Write(aspx.page, End Render); CheckRemainingAsyncTasks(false); } }
至此整个IIS处理完整请求就结束了列举了各个关键处理阶段的处理函数。当我们了解.net framework内部处理机制后能够使我们理解运行机制和本质对开发人员来说这很重要不能只停留在会用会写的阶段而且要知道其内部原理。这样不仅可以帮助我们编写更高效的代码,同时可以学习并借鉴微软的面向对象的编程思想受益颇多