你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)
一、写在前面
最近有时间,顺便将这系列洗完,接着上文:IIS各个版本知识总结
这篇文章原本计划写到HttpHandler为止,但限于篇幅就写到httpmodule
本文有不足之处,求指正,希望我能将它分析透彻.
二、回顾--我们还是从IIS说起
从上文(IIS各个版本知识总结)可以很清楚地意思到经典模式和集成模式的区别:集成模式是一个伟大的改进,让IIS集成了.NET功能(不在依靠之前IIS版本的aspnet_ISPAI.DLL).
所以,对于我们所开发的ASP.NET程序而言,这些完全不必知道;但运行环境自己必须知道发生了什么情况.
所以两者的主要区别在于:从w3wp.exe初始化httpapplication这一阶段.
三、看看经典模式(包括IIS6)的过程
IIS的处理进程到w3wp这一阶段后,iis会通过com的方式创建AppManagerAppDomainFactory对象,AppManagerAppDomainFactory会
在Create方法中创建ISAPIRuntime对象.代码如下.
using System; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Security.Permissions; using System.Web.Util; namespace System.Web.Hosting { [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] public sealed class AppManagerAppDomainFactory : IAppManagerAppDomainFactory { private ApplicationManager _appManager; public AppManagerAppDomainFactory() { this._appManager = ApplicationManager.GetApplicationManager(); this._appManager.Open(); } [return: MarshalAs(UnmanagedType.Interface)] public object Create(string appId, string appPath) { object result; try { if (appPath[0] == ‘.‘) { FileInfo fileInfo = new FileInfo(appPath); appPath = fileInfo.FullName; } if (!StringUtil.StringEndsWith(appPath, ‘\\‘)) { appPath += "\\"; } ISAPIApplicationHost appHost = new ISAPIApplicationHost(appId, appPath, false); ISAPIRuntime iSAPIRuntime = (ISAPIRuntime)this._appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost, false, null); iSAPIRuntime.StartProcessing(); result = new ObjectHandle(iSAPIRuntime); } catch (Exception) { throw; } return result; } public void Stop() { this._appManager.Close(); } internal static string ConstructSimpleAppName(string virtPath) { if (virtPath.Length <= 1) { return "root"; } return virtPath.Substring(1).ToLower(CultureInfo.InvariantCulture).Replace(‘/‘, ‘_‘); } } }
最终将流程交由ProcessRequest处理,代码如下.接着如红色处,由HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest)处理
public int ProcessRequest(IntPtr ecb, int iWRType) { IntPtr intPtr = IntPtr.Zero; if (iWRType == 2) { intPtr = ecb; ecb = UnsafeNativeMethods.GetEcb(intPtr); } ISAPIWorkerRequest iSAPIWorkerRequest = null; int result; try { bool useOOP = iWRType == 1;
//注:internal abstract class ISAPIWorkerRequest : HttpWorkerRequest iSAPIWorkerRequest = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP); iSAPIWorkerRequest.Initialize(); string appPathTranslated = iSAPIWorkerRequest.GetAppPathTranslated(); string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal; if (appDomainAppPathInternal == null || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal)) { HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest); result = 0; } else { HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated })); result = 1; } } catch (Exception ex) { //.................................. } return result; }
ISAPIWorkerRequest是对请求信息的一层C++封装.
四、HttpRuntime中发生的事情
接着上面 HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);
internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) { RequestQueue requestQueue = HttpRuntime._theRuntime._requestQueue; wr.UpdateInitialCounters(); if (requestQueue != null) { wr = requestQueue.GetRequestToExecute(wr); } if (wr != null) { HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr); wr.ResetStartTime(); HttpRuntime.ProcessRequestNow(wr); } } internal static void ProcessRequestNow(HttpWorkerRequest wr) { HttpRuntime._theRuntime.ProcessRequestInternal(wr); }
我们看到方法进入
private void ProcessRequestInternal(HttpWorkerRequest wr)
其结构如下
private void ProcessRequestInternal(HttpWorkerRequest wr) { Interlocked.Increment(ref this._activeRequestCount); if (this._disposingHttpRuntime) { try { wr.SendStatus(503, "Server Too Busy"); wr.SendKnownResponseHeader(12, "text/html; charset=utf-8"); byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>"); wr.SendResponseFromMemory(bytes, bytes.Length); wr.FlushResponse(true); wr.EndOfRequest(); } finally { Interlocked.Decrement(ref this._activeRequestCount); } return; } HttpContext httpContext; try { httpContext = new HttpContext(wr, false); } catch { try { wr.SendStatus(400, "Bad Request"); wr.SendKnownResponseHeader(12, "text/html; charset=utf-8"); byte[] bytes2 = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>"); wr.SendResponseFromMemory(bytes2, bytes2.Length); wr.FlushResponse(true); wr.EndOfRequest(); return; } finally { Interlocked.Decrement(ref this._activeRequestCount); } } wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, httpContext); HostingEnvironment.IncrementBusyCount(); try { try { this.EnsureFirstRequestInit(httpContext); } catch { if (!httpContext.Request.IsDebuggingRequest) { throw; } } httpContext.Response.InitResponseWriter(); IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext); if (applicationInstance == null) { throw new HttpException(SR.GetString("Unable_create_app_object")); } if (EtwTrace.IsTraceEnabled(5, 1)) { EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, httpContext.WorkerRequest, applicationInstance.GetType().FullName, "Start"); } if (applicationInstance is IHttpAsyncHandler) { IHttpAsyncHandler httpAsyncHandler = (IHttpAsyncHandler)applicationInstance; httpContext.AsyncAppHandler = httpAsyncHandler; httpAsyncHandler.BeginProcessRequest(httpContext, this._handlerCompletionCallback, httpContext); } else { applicationInstance.ProcessRequest(httpContext); this.FinishRequest(httpContext.WorkerRequest, httpContext, null); } } catch (Exception e) { httpContext.Response.InitResponseWriter(); this.FinishRequest(wr, httpContext, e); } }
传说中的HttpApplication就是在这里初始化的.
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);//因为HttpApplication实现了IHttpHandler接口
最终通过BuildManager.GetGlobalAsaxType()获取对应的Global.asax所告知的类型进行HttpApplication的实例化.
internal static IHttpHandler GetApplicationInstance(HttpContext context) { if (HttpApplicationFactory._customApplication != null) { return HttpApplicationFactory._customApplication; } if (context.Request.IsDebuggingRequest) { return new HttpDebugHandler(); } HttpApplicationFactory._theApplicationFactory.EnsureInited(); HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context); return HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context); }
private HttpApplication GetNormalApplicationInstance(HttpContext context) { HttpApplication httpApplication = null; lock (this._freeList) { if (this._numFreeAppInstances > 0) { httpApplication = (HttpApplication)this._freeList.Pop(); this._numFreeAppInstances--; if (this._numFreeAppInstances < this._minFreeAppInstances) { this._minFreeAppInstances = this._numFreeAppInstances; } } } if (httpApplication == null) { httpApplication = (HttpApplication)HttpRuntime.CreateNonPublicInstance(this._theApplicationType); using (new ApplicationImpersonationContext()) { httpApplication.InitInternal(context, this._state, this._eventHandlerMethods);//注意:这里是主战场 } } if (AppSettings.UseTaskFriendlySynchronizationContext) { httpApplication.ApplicationInstanceConsumersCounter = new CountdownTask(1); httpApplication.ApplicationInstanceConsumersCounter.Task.ContinueWith(delegate(Task _, object o) { HttpApplicationFactory.RecycleApplicationInstance((HttpApplication)o); }, httpApplication, TaskContinuationOptions.ExecuteSynchronously); } return httpApplication; }
五、主战场中的发生的事情
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 IL_6B; } finally { context.HideRequestResponse = false; this._hideRequestResponse = false; } } this.InitModules(); IL_6B: 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 error) { this.RecordError(error); } } 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 HttpApplication.PipelineStepManager(this); } else { this._stepManager = new HttpApplication.ApplicationStepManager(this); } this._stepManager.BuildSteps(this._resumeStepsWaitCallback); } finally { this._initInternalCompleted = true; context.ConfigurationPath = null; this._initContext.ApplicationInstance = null; this._initContext = null; } } catch { throw; } }
待续................................
六、求关注、求推荐
兄台给点鼓励吧 O(∩_∩)O~,你的鼓励是我继续写好这一系列的理由
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。