你必须知道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~,你的鼓励是我继续写好这一系列的理由

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

时间: 2024-09-30 05:21:39

你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)的相关文章

你必须知道ASP.NET知识------关于动态注册httpmodule(对不起汤姆大叔)

一.关于动态注册的问题 很多人看过汤姆大叔的MVC之前的那点事儿系列(6):动态注册HttpModule ,其实汤姆大叔没有发现httpmodule动态注册的根本机制在哪里. 亦即:怎么动态注册?为什么能够动态注册? 汤姆大叔给了如下开篇 通过前面的章节,我们知道HttpApplication在初始化的时候会初始化所有配置文件里注册的HttpModules,那么有一个疑问,能否初始化之前动态加载HttpModule,而不是只从Web.config里读取? 答案是肯定的, ASP.NET MVC3

asp相关知识整理

WWW----World Wide Web(万维网) URL----Uniform Resource Locator(统一资源定位符) HTTP----Hyper Text Transfer Protocol(超文本传输协议) HTML----Hyper Text Markup Language(超文本标记语言) XML----Extensible Markup Language(可扩展标记语言) ODBC----Open DataBase Connectivity(开放数据库连接标准) DLL

ASP.NET知识重新梳理(二)------关于ASP.NET知识学习流程的一些理解

ASP.NET知识的学习流程我大概是这么理解的,首先我们必须打好C#的基础,若是之前没有学过C++之类的面向对象语言作为基础,还是要好好看看继承派生多态之类的区别和联系的:其次,当今的编程不仅仅只是我们在学校课堂上所学的控制台应用程序,我们还要学习winfom,WPF之类的本地窗体应用:第三,每个公司的技术方向都是不同的,但是共同的地方是都需要数据库来存储自己的数据,而且sqlserver,mysql,oracle都是大同小异的,所以如果你之前的编程学的不是很好,做一个DBA吧,入门难度也不是很

ASP.NET知识重新梳理(三)------C#基础语法

C#基础语法:1.基本语法:无论代码中是否有空格,回车符,tab字符(统称为空白字符),C#编译器都不考虑这些字符: C#字符由一系列语句组成,每个语句由一个分号来结束: C#是一个块结构的语言,所有的语句都是代码块的一部分,这些块用花括号来界定("{"和"}"): C#中的注释:标记注释/*...*/ 单行注释//... 单行注释/// (可以配置VS,在编译项目时,提取这些注释后面的文本,创建一个特殊格式的文本文件,该文件可用于 创建文档说明书): C#代码是区

ASP.NET知识重新梳理(四)------关于流程控制语句

学习C语言的时候,我们就已经学习过流程控制语句, 也就是顺序,条件,循环三种.在TIOBE编程语言排行榜单中前几位的流程控制语句貌似几乎相同,所以说一通百通嘛, 就是这个道理. 一.顺序执行语句:顾名思义,按照顺序依次执行 二.条件语句: 1.if-else语句 1.只包含if关键词,没有else的情况: if (expression)     statement1 2.包含if和else的分支的情况: if (expression)     statement1;    else     st

ASP.NET知识集

ASP.NET知识集 编辑删除转载2015-06-23 16:31:55 标签:it //删除指定行数据时,弹出询问对话框 ((LinkButton)(e.Row.Cell[7].Controls[0]).Attributes.Add("onclick","return confirm('是否删除当前数据!')"); //注登录,清楚cookie.session session["userinfo"]=null; CookieHelper.wri

ASP.NET 知识体系结构

以下是我根据自身的情况来总结的ASP.NET 知识体系 ASP.NET 知识体系 C#--C#-知识梳理 ASP.NET WinForm ASP.NET MVC EF

用ASP编程控制在IIS建立Web站点

''******************************************************* '' 创建一个WebServer '' 必须参数:WRoot,为创建站点的物理目录:WComment为站点说明:WPort为站点端口:ServerRun为是否自动运行 '' 当创建成功时返回1,失败时提示退出并返回0,当创建站点成功但启动失败时返回2 ''******************************************************* ''******

HTTP -&gt; Asp.net (第一篇)

当用户在浏览器输入一个URL地址后,浏览器会发送一个请求到服务器.这时候在服务器上第一个负责处理请求的是IIS.然后IIS再根据请求的URL扩展名将请求分发给不同的ISAPI处理. 流程如下: 1.IIS => aspnet_isapi阶段 ISAPI是一个底层的WIN32 API,开发者可以使用这些接口深入到IIS,让IIS支持各种其他处理程序.ISAPI是一个桥接口,通常用于高层次的工具与IIS之间的接驳.例如Windows下的Apache与Tomcat就是构建于ISAPI之上.ISAPI是