你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)

一、写在前面

  最近有时间,顺便将这系列洗完,接着上文:IIS各个版本知识总结

  这篇文章原本计划写到HttpHandler为止,但限于篇幅就写到httpmodule

  本文有不足之处,求指正,希望我能将它分析透彻.

二、回顾--我们还是从IIS说起

  从上文(IIS各个版本知识总结)可以很清楚地意思到经典模式和集成模式的区别:集成模式是一个伟大的改进,让IIS集成了.NET功能(不在依靠之前IIS版本的aspnet_ISPAI.DLL).

  所以,对于我们所开发的ASP.NET程序而言,这些完全不必知道;但运行环境自己必须知道发生了什么情况.

  所以两者的主要区别在于:从w3wp.exe初始化httpapplication这一阶段.

 

三、看看经典模式(包括IIS6)的过程

你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)

IIS的处理进程到w3wp这一阶段后,iis会通过com的方式创建AppManagerAppDomainFactory对象,AppManagerAppDomainFactory会

在Create方法中创建ISAPIRuntime对象.代码如下.

你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)
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('/', '_');

        }

    }

}
View Code

最终将流程交由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);

你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)
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);

        }
View Code

我们看到方法进入

private void ProcessRequestInternal(HttpWorkerRequest wr)

其结构如下

你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)
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);

            }

        }
View Code

传说中的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~,你的鼓励是我继续写好这一系列的理由

你可能感兴趣的:(asp.net)