ASP.NET的运行原理与运行机制 如何:为 IIS 7.0 配置 <system.webServer> 节

 ASP.NET的运行原理

 

 

  当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块。在ASP.NET 3.5中,这个模块叫做HttpHandler(HTTP处理程序组件),之所以.aspx文件可以被服务器处理,就是因为在服务器端有默认的HttpHandler专门处理.aspx文件。IIS在将这条请求发送给能够处理这个请求的模块之前,还需要经过一些HttpModule的处理,这些都是系统默认的Modules(用于获取当前应用程序的模块集合),在这个HTTP请求传到HttpHandler之前要经过不同的HttpModule的处理。这样做的好处,一是为了一些必需的过程,二是为了安全性,三是为了提高效率,四是为了用户能够在更多的环节上进行控制,增强用户的控制能力。ASP.NET 3.5运行原理如图1.1所示。

图1.1  ASP.NET 3.5运行原理

  说明:HttpModule模块是一个组件,可以注册为ASP.NET 3.5请求生命周期的一部分,当处理该组件时,该组件可以读取或更改请求或响应。HttpModule模块通常用于执行需要监视每个请求的特殊任务,如安全或站点统计信息。

 (PS:

  HttpModule 概述:

  暂时先不考虑我们自己实现Http Module的情况。在.Net中,Http Module 是实现了IHttpModule接口的程序集。IHttpModule 接口本身并没有什么好大写特写的,由它的名字可以出,它不过是一个普普通通的接口而已。实际上,我们关心的是实现了这些接口的类,如果我们也编写代码实现了这个接口,那么有什么用途。一般来说,我们可以将Asp.Net中的事件分成三个级别,最顶层是 应用程序级事件、其次是页面级事件、最下面是控件级事件,事件的触发分别与 应用程序周期、页面周期、控件周期紧密相关。而 Http Module 的作用是与应用程序事件 密切相关的。

  我们通过Http Module在Http请求管道(Pipeline)中注册期望对应用程序事件做出反应的方法,在相应的事件触发的时候(比如说BeginRequest事件,它在应用程序收到一个Http请求并即将对其进行处理时触发),便会调用Http Module注册了的方法,实际的工作在这些方法中执行。.Net 本身已经有很多的Http Module,其中包括 表单验证Module(FormsAuthenticationModule), Session 状态Module(SessionStateModule),输出缓存Module (OutputCacheModule)等。

更多了解:http://www.cnblogs.com/jimmyzhang/archive/2007/11/25/971878.html

  )

  ASP.NET 3.5运行机制如图1.2所示。

  通常情况下,ASP.NET框架搭建在Windows Server(服务器版操作系统)+IIS(Web服务器,是Internet信息服务管理器的英文缩写)环境中,在安装.NET Framework时,安装程序将会在IIS中注册ASP.NET所需的ISAPI扩展(aspnet_isapi.dll),这就使得作为ASP.NET宿主的IIS在接收到客户端的HTTP请求后,将响应请求的控制权交给ASP.NET运行。

  ASP.NET运行时接收到请求后,会判断站点是否为第一次被访问,如果是第一次访问,则运行初始化工作(如加载Bin目录中的DLL动态链接库,读取Web.Config网站配置文件,初始化HttpApplication实例,编译和加载Global.asax文件等)。ASP.NET运行时还负责创建请求响应线程的HttpContext上下文实例和创建承载响应结果的HttpTextWriter实例。然后,ASP.NET运行时寻找合适的HttpHandler(通常就是具有的ASP.NET页面)处理HTTP请求,并等HttpHandler返回请求处理结果。最后,ASP.NET运行时在完成一些后续工作之后,如保存Session、异常处理,再通过IIS把响应结构返回给客户端。

图1.2  ASP.NET 3.5运行机制

  注意:ASP.NET ISAPI工作的主要任务就是安排ASPNET_WP.exe处理请求,并监视ASPNET_ WP.exe进程的执行情况,如果ASPNET_WP.exe进程不能完成任务,ASP.NET ISAPI就安排一个新的ASPNET_WP.exe来处理工作。ASPNET_WP.exe的主要任务是将请求交给一系列称为HTTP管道的托管对象。如果把ASP.NET ISAPI比做销售商,那么ASPNET_WP.exe就是生产商,而HTTP管道就是生产的流水线,负责流水线的小组就是HttpRuntime。生产商ASPNET_WP.exe会将订单(HTTP请求)交给HttpRuntime小组的工作人员ProcessRequest(HttpWorkerRequest wr),HttpRuntime根据内部的分工,最终由ProcessRequestInternal(HttpWorkerRequest wr)在流水线上进行生产。

向模块注册中添加 precondition 属性,并将其值设置为managedHandler。

此条件会导致仅在请求 ASP.NET 应用程序资源(例如 .aspx 文件或托管处理程序)时才调用该模块。该资源中不包括静态文件(例如 .htm 文件)。

其 configuration 节将类似于以下示例。

复制代码
<configuration>
  <system.webServer>
    <modules>
      <add name="CustomModule" type="Samples.CustomModule" 
           precondition="managedHandler" />
    </modules>
    <defaultDocument>
      <files>
        <add value="Products.aspx" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>
复制代码
Integrated mode — 集成模式
IIS 7.0 中的一种配置,其中,IIS 和 ASP .NET 基于支持使用 .NET Framework 和本机组件创建的组件的管线共享请求处理。在集成模式中,ASP .NET 组件(如 HTTP 模块)可用于管理所有 Web 请求,其中包括那些对非 ASP .NET 资源的请求。
复制代码
 <system.webServer>
    <!--集成模式-->
    <modules>
      <add name="BaseHttpHandler" type="Frame.Core.BaseHttpHandler" />
    </modules>
    <handlers>
 </system.webServer>
复制代码

 zhongkeMVC原理:自定义handler(必须实现IhttpModel,想用请求管道的19个事件就必须实现,init是最主要得方法)并且在web.config注册

通过web.config配置注册模块托管代码,截获每次请求到baseHandler,在此分析请求地址中的controller、action,然后反射调用相应的方法,通过VTempalte模板替换所有HTML中相应的值,最后返回给用户。

ps:baseHandler 在global之前

程序启动先根据web.config去创建baseHandler并且执行他的init方法,还有VT模板的一些初始化 方法,此时执行了三个方法

this.OnInit(EventArgs.Empty);
this.OnLoad(EventArgs.Empty);
this.OnRender(EventArgs.Empty);

然后才执行 global中的 Application_Start事件(Application_Start 和baseHandler中init只是程序启动时执行一次,每次请求的时候不再执行那两个方法)

 

每次回话开始的的时候先执行global中Session_Start然后执行正常的每次请求

每次请求 先执行Application_BeginRequest  然后是baseHandler中的那通过 IHttpHandler.ProcessRequest 调用那三个初始化方法

 public class BaseHttpHandler : TemplatePageBase, IHttpModule, IRequiresSessionState
TemplatePageBase 是他的父类  所以先之心BaseHttpHandler 中的方法

2016-7-25
现在的理解 他这个框架没用注册任何时间 就是利用 第八个创建请求对象的的时候 就创建了httphandler 然后到11 12事件之间的时候执行里面的processrequest方法,根据分析地址去找控制器 去找html文件, 替换模板内容

 一般情况下  称HttpModel为过滤器  

global中有些方法是和管道中的时间对应的  不过是先执行自定义模块中管道中绑定的方法,然后在执行global中的 一一对应

 processRequest调用管道19个事件  到第12个的时候  有一个hanler的processrequest的方法

一般处理程序和aspx页到12个都执行这个方法

一般处理程序:是程序员写的处理代码

aspx:是页面的整个生命周期

托管和非托管是什么意思?

托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。 Unmanaged Code - 非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。

MVC怎么进入管道的

httpapplaction 创建之后会遍历创建所有module 包括 URLRoutingMdeule路由处理

遍历完URLRoutingMdeule 执行他的init方法,完成了请求管道中第七个事件的注册
通过反编译可以看到 URLRoutingMdeule 注册了第七个事件
遍历完 执行 processRequest 开始进入管道 到第七个事件的时候
执行注册的方法,根据路由数据创建MVChandler 实现了Ihttphanlder
到十一、十二个事件之间 执行 processrequest(去找控制器 、方法)

这个processrequest
asp.net:page_load一系列方法
MVC:去匹配控制器、方法
一般处理程序:程序员直接实现代码

一系列处理 到httpruntime 然后创建 httpcontext 并且对象池获取 Application

然后进入管道piplines

7/8事件之间  获取 httpHandler  

MVC 生命周期

 https://www.cnblogs.com/fzrain/p/3651693.html

HttpApplication的处理管道19个事件。

https://www.cnblogs.com/wolf-sun/p/5236185.html

HttpApplication对象是由Asp.net帮助我们创建的,它是asp.net中处理请求的重要对象。为了便于扩展,HttpApplication采用处理管道的方式进行处理,将处理的步骤分为多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以定义一个请求的扩展过程。

对于HttpApplication,到ASP.NET 4.0,提供了19个标准事件。

1.BeginRequest:asp.net开始处理请求的第一个事件,表示处理的开始。

2.AuthenticateRequest:验证请求,一般用来取得请求的用户信息。

3.PostAuthenticateRequest:已经获取请求的用户信息。

4.AuthorizeRequest:授权,一般用来检查用户的请求是否获得权限。

5.PostAuthorizeRequest:用户请求已经获得授权。

6.ResolveRequestCache:获取以前处理缓存的处理结果,如果以前缓存过,那么,不用再进行请求的处理工作,直接返回缓存的结果。

7.PostResolveRequestCache:已经完成缓存的处理工作。

8.PostMapRequestHandler:已经根据用户的请求,创建了请求的处理器对象。

9.AcquireRequestState:取得请求的状态,一般用于session

10.PostAcquireRequestState:已经获得了session

11.PreRequestHandlerExecute:准备执行处理程序。

12.PostRequestHandlerExecute:已经执行了处理程序

13.ReleaseRequestState:释放请求的状态。

14.PostReleaseRequestState:已经释放了请求的状态。

15.UpdateRequestCache:更新缓存。

16.PostUpdateRequestCache:已经更新了缓存。

17.LogRequest:请求的日志操作

18.PostLogRequest:已经完成请求的日志操作。

19.EndRequest:本次请求处理完成。

ASP.NET MVC中的Global.asax文件

1.global.asax文件概述 

global.asax这个文件包含全局应用程序事件的事件处理程序。它响应应用程序级别和会话级别事件的代码。  
运行时, Global.asax 将被编译成一个动态生成的 .NET Framework 类,该类是从HttpApplication基类派生的。
因此在global.asax中的代码可以访问HttpApplication类中所有的public或者protected的成员
global.asax不被用户直接请求,但global.asax中的代码会被自动执行来响应特定的应用程序事件。
global.asax是可选的,而且在一个web项目中是唯一的,它应该处于网站的根目录。

2.一个请求的完整处理过程

以下过程由Internet Information Service(inetinfo.exe)(IIS)执行
1.客户端发出请求
2.验证请求
3.给请求授权
4.确定请求的缓存
5.获取缓存状态
6.在请求的处理程序执行前
7.http处理程序执行请求 (asp.net页面由aspnet_wp.exe执行)
8.在请求的处理程序执行后
9.释放请求状态
10.更新请求缓存
11.请求结束

3.global.asax中的事件

global.asax中的所有事件可以分成两种,一种是满足特定事件时才会被触发,一种是每次请求都会被按照顺序执行的事件。

复制代码
 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //在Web应用程序的生命周期里就执行一次
            //在应用程序第一次启动和应用程序域创建事被调用
            //适合处理应用程序范围的初始化代码
        }

        void Application_End(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //在应用程序关闭时运行的代码,在最后一个HttpApplication销毁之后执行
            //比如IIS重启,文件更新,进程回收导致应用程序转换到另一个应用程序域
        }

        void Session_Start(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //会话开始时执行
        }

        void Session_End(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //会话结束或过期时执行
            //不管在代码中显式的清空Session或者Session超时自动过期,此方法都将被调用
        }

        void Application_Init(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //在每一个HttpApplication实例初始化的时候执行
        }

        void Application_Disposed(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //在应用程序被关闭一段时间之后,在.net垃圾回收器准备回收它占用的内存的时候被调用。
            //在每一个HttpApplication实例被销毁之前执行
        }

        void Application_Error(object sender, EventArgs e)
        {
            //不是每次请求都调用
            //所有没有处理的错误都会导致这个方法的执行
        }


        /*********************************************************************/
        //每次请求都会按照顺序执行以下事件
        /*********************************************************************/

        void Application_BeginRequest(object sender, EventArgs e)
        {
            //每次请求时第一个出发的事件,这个方法第一个执行
        }

        void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            //在执行验证前发生,这是创建验证逻辑的起点
        }

        void Application_AuthorizeRequest(object sender, EventArgs e)
        {
            //当安全模块已经验证了当前用户的授权时执行
        }

        void Application_ResolveRequestCache(object sender, EventArgs e)
        {
            //当ASP.NET完成授权事件以使缓存模块从缓存中为请求提供服务时发生,从而跳过处理程序(页面或者是WebService)的执行。
            //这样做可以改善网站的性能,这个事件还可以用来判断正文是不是从Cache中得到的。
        }

        //------------------------------------------------------------------------
        //在这个时候,请求将被转交给合适程序。例如:web窗体将被编译并完成实例化
        //------------------------------------------------------------------------

        void Application_AcquireRequestState(object sender, EventArgs e)
        {
            //读取了Session所需的特定信息并且在把这些信息填充到Session之前执行
        }

        void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            //在合适的处理程序执行请求前调用
            //这个时候,Session就可以用了
        }

        //-------------------------------------------------
        //在这个时候,页面代码将会被执行,页面呈现为HTML
        //-------------------------------------------------

        void Application_PostRequestHandlerExecute(object sender, EventArgs e)
        {
            //当处理程序完成对请求的处理后被调用。
        }

        void Application_ReleaseRequestState(object sender, EventArgs e)
        {
            //释放请求状态
        }

        void Application_UpdateRequestCache(object sender, EventArgs e)
        {
            //为了后续的请求,更新响应缓存时被调用
        }

        void Application_EndRequest(object sender, EventArgs e)
        {
            //EndRequest是在响应Request时最后一个触发的事件
            //但在对象被释放或者从新建立以前,适合在这个时候清理代码
        }

        void Application_PreSendRequestHeaders(object sender, EventArgs e)
        {
            //向客户端发送Http标头之前被调用
        }

        void Application_PreSendRequestContent(object sender, EventArgs e)
        {
            //向客户端发送Http正文之前被调用
        }
    }
复制代码

原文: https://technet.microsoft.com/zh-cn/sysinternals/bb763179.aspx

          https://www.cnblogs.com/lgxlsm/p/5573088.html

原文地址:https://www.cnblogs.com/xiaoshi657/p/4113779.html