ASP.NET IIS 5.0 和 6.0 的应用程序生命周期概述

发布时间 2023-10-08 18:06:42作者: Nine4酷

一般应用程序生命周期
生命周期事件和 Global.asax 文件
编译生命周期
应用程序重新启动
显示 2 更多
本主题概述了 ASP.NET 应用程序的生命周期,列出了重要的生命周期事件,并描述了您编写的代码如何适应应用程序生命周期。本主题中的信息适用于 IIS 5.0 和 IIS 6.0。有关 IIS 7.0 中 ASP.NET 应用程序生命周期的信息,请参阅 IIS 7.0 ASP.NET 应用程序生命周期概述。

在 ASP.NET 中,必须执行多个处理步骤才能初始化 ASP.NET 应用程序并处理请求。此外,ASP.NET 只是 Web 服务器体系结构的一部分,它为浏览器发出的请求提供服务。了解应用程序生命周期非常重要,这样您就可以在适当的生命周期阶段编写代码以实现预期效果。

一般应用程序生命周期
下表描述了 ASP.NET 应用程序生命周期的各个阶段。

阶段

描述

用户从 Web 服务器请求应用程序资源。

ASP.NET 应用程序的生命周期从浏览器发送到 Web 服务器的请求开始(对于 ASP.NET 应用程序,通常是 IIS)。ASP.NET 是 Web 服务器下的 ISAPI 扩展。当 Web 服务器收到请求时,它会检查所请求文件的文件扩展名,确定哪个 ISAPI 扩展名应处理该请求,然后将请求传递给相应的 ISAPI 扩展名。ASP.NET 处理已映射到它的文件扩展名,例如.aspx、.ascx、.ashx 和 .asmx。

注意

如果文件扩展名尚未映射到 ASP.NET,则 ASP.NET 将不会收到请求。对于使用 ASP.NET 身份验证的应用程序,了解这一点非常重要。例如,由于.htm文件通常不会映射到 ASP.NET,因此 ASP.NET 不会对.htm文件的请求执行身份验证或授权检查。因此,即使文件仅包含静态内容,如果希望 ASP.NET 检查身份验证,也请使用映射到 ASP.NET 的文件扩展名(如 .aspx)创建文件。

注意

如果创建自定义处理程序来为特定文件扩展名提供服务,则必须将该扩展名映射到 IIS 中的 ASP.NET,并在应用程序的 Web.config 文件中注册该处理程序。有关详细信息,请参阅 HTTP 处理程序和 HTTP 模块概述。

ASP.NET 收到应用程序的第一个请求。

当 ASP.NET 收到对应用程序中任何资源的第一个请求时,名为 ApplicationManager 的类会创建一个应用程序域。应用程序域为全局变量提供应用程序之间的隔离,并允许单独卸载每个应用程序。在应用程序域中,将创建名为 HostingEnvironment 的类的实例,该实例提供对有关应用程序的信息(如存储应用程序的文件夹的名称)的访问。

下图说明了这种关系:

应用形貌概述图形
如果需要,ASP.NET 还会编译应用程序中的顶级项,包括 App_Code 文件夹中的应用程序代码。有关详细信息,请参阅本主题后面的“编译生命周期”。

为每个请求创建 ASP.NET 核心对象。

创建应用程序域并实例化 HostingEnvironment 对象后,ASP.NET 创建并初始化核心对象,如 HttpContext、HttpRequest 和 HttpResponse。类包含特定于当前应用程序请求的对象,例如 HttpRequest 和 HttpResponse 对象。HttpRequest 对象包含有关当前请求的信息,包括 Cookie 和浏览器信息。对象包含发送到客户端的响应,包括所有呈现的输出和 Cookie。

将 HttpApplication 对象分配给请求

初始化所有核心应用程序对象后,通过创建 HttpApplication 类的实例来启动应用程序。如果应用程序具有 Global.asax 文件,则 ASP.NET 创建从 HttpApplication 类派生的 Global.asax 类的实例,并使用派生类来表示应用程序。

注意

首次在应用程序中请求 ASP.NET 页或进程时,将创建一个新的 HttpApplication 实例。但是,为了最大限度地提高性能,HttpApplication 实例可以重用于多个请求。

创建 HttpApplication 实例时,还会创建任何已配置的模块。例如,如果应用程序配置为这样做,ASP.NET 创建一个会话状态模块。创建所有已配置的模块后,将调用 HttpApplication 类的 Init 方法。

下图说明了这种关系:

应用程序环境图形
请求由 HttpApplication 管道处理。

处理请求时,类将执行以下事件。这些事件对想要扩展 HttpApplication 类的开发人员特别感兴趣。

验证请求,该请求将检查浏览器发送的信息并确定它是否包含潜在的恶意标记。有关更多信息,请参阅验证请求和脚本攻击概述。

如果已在 Web.config 文件的 UrlMappingsSection 部分中配置了任何 URL,请执行 URL 映射。

引发 BeginRequest 事件。

引发身份验证请求事件。

引发 PostAuthenticateRequest 事件。

引发授权请求事件。

引发 PostAuthorizeRequest 事件。

引发 ResolveRequestCache 事件。

引发 PostResolveRequestCache 事件。

根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 来处理请求的类。如果请求是针对从 Page 类派生的对象(页面),并且需要编译该页面,则 ASP.NET 在创建页面实例之前编译该页面。

引发 PostMapRequestHandler 事件。

引发 AcquireRequestState 事件。

引发 PostAcquireRequestState 事件。

引发 PreRequestHandlerExecute 事件。

为请求调用相应 IHttpHandler 类的 ProcessRequest 方法(或异步版本 IHttpAsyncHandler.BeginProcessRequest)。例如,如果请求是针对页面的,则当前页面实例将处理该请求。

引发 PostRequestHandlerExecute 事件。

引发 ReleaseRequestState 事件。

引发 PostReleaseRequestState 事件。

如果定义了 Filter 属性,则执行响应筛选。

引发 UpdateRequestCache 事件。

引发 PostUpdateRequestCache 事件。

引发 EndRequest 事件。

引发 PreSendRequestHeaders 事件。

引发 PreSendRequestContent 事件。

生命周期事件和 Global.asax 文件
在应用程序生命周期中,应用程序会引发您可以处理的事件,并调用您可以重写的特定方法。若要处理应用程序事件或方法,可以在应用程序的根目录中创建一个名为 Global.asax 的文件。

如果创建 Global.asax 文件,ASP.NET 将其编译为派生自 HttpApplication 类的类,然后使用该派生类来表示该应用程序。

HttpApplication 的实例一次只处理一个请求。这简化了应用程序事件处理,因为在访问应用程序类时不需要锁定应用程序类中的非静态成员。这还允许您将特定于请求的数据存储在应用程序类的非静态成员中。例如,可以在 Global.asax 文件中定义一个属性,并为其分配一个特定于请求的值。

ASP.NET 使用命名约定Application_event(如 Application_BeginRequest)自动将应用程序事件绑定到 Global.asax 文件中的处理程序。这类似于 ASP.NET 页方法自动绑定到事件(如页的Page_Load事件)的方式。有关详细信息,请参阅 ASP.NET 页面生命周期概述。

Application_Start 和 Application_End 方法是不表示 HttpApplication 事件的特殊方法。ASP.NET 应用程序域的生存期内调用它们一次,而不是针对每个 HttpApplication 实例调用它们。

下表列出了在应用程序生命周期中使用的一些事件和方法。事件比列出的事件多得多,但它们并不常用。

事件或方法

描述

Application_Start

请求 ASP.NET 应用程序中的第一个资源(如页面)时调用。Application_Start方法在应用程序的生命周期中仅调用一次。可以使用此方法执行启动任务,例如将数据加载到缓存中和初始化静态值。

在应用程序启动期间,应仅设置静态数据。不要设置任何实例数据,因为它仅对创建的 HttpApplication 类的第一个实例可用。

Application_event

在应用程序生命周期中的适当时间引发,如本主题前面的应用程序生命周期表中所列。

Application_Error可以在应用程序生命周期的任何阶段提出。

Application_EndRequest 是唯一保证在每个请求中引发的事件,因为请求可能会短路。例如,如果两个模块处理 Application_BeginRequest 事件,而第一个模块引发异常,则不会为第二个模块调用 Application_BeginRequest 事件。但是,始终调用 Application_EndRequest 方法以允许应用程序清理资源。

初始化

在创建所有模块后,为 HttpApplication 类的每个实例调用一次。

处理

在销毁应用程序实例之前调用。可以使用此方法手动释放任何非托管资源。有关更多信息,请参见清理非托管资源。

Application_End

在卸载应用程序之前,应用程序的每个生存期调用一次。

编译生命周期
向应用程序发出第一个请求时,ASP.NET 按特定顺序编译应用程序项。要编译的第一项称为顶级项。在第一个请求之后,仅当依赖项发生更改时,才会重新编译顶级项。下表描述了 ASP.NET 顶级项的编译顺序。

项目

描述

App_GlobalResources

编译应用程序的全局资源并生成资源程序集。应用程序的 Bin 文件夹中的任何程序集都链接到资源程序集。

App_WebResources

创建并编译 Web 服务的代理类型。生成的 Web 引用程序集将链接到资源程序集(如果存在)。

Web.config 文件中定义的配置文件属性

如果在应用程序的 Web.config 文件中定义了配置文件属性,则会生成一个包含配置文件对象的程序集。

App_Code

生成源代码文件并创建一个或多个程序集。所有代码程序集和配置文件程序集都链接到资源和 Web 引用程序集(如果有)。

全球

应用程序对象已编译并链接到以前生成的所有程序集。

编译应用程序的顶级项后,ASP.NET 根据需要编译文件夹、页面和其他项。下表描述了 ASP.NET 文件夹和项目的编译顺序。

项目

描述

App_LocalResources

如果包含所请求项的文件夹包含App_LocalResources文件夹,则会编译本地资源文件夹的内容并将其链接到全局资源程序集。

单个网页(.aspx文件)、用户控件(.ascx 文件)、HTTP 处理程序(.ashx 文件)和 HTTP 模块(.asmx 文件)

根据需要编译并链接到本地资源程序集和顶级程序集。

主题、母版页、其他源文件

单个主题、母版页和页面引用的其他源代码文件的外观文件在编译引用页时进行编译。

编译的程序集缓存在服务器上,并在后续请求中重复使用,并且只要源代码不变,就会在应用程序重新启动时保留。

由于应用程序是在第一个请求上编译的,因此对应用程序的初始请求可能需要比后续请求长得多的时间。您可以预编译应用程序以减少第一个请求所需的时间。有关更多信息,请参见如何:预编译 ASP.NET 网站项目。

应用程序重新启动
修改 Web 应用程序的源代码将导致 ASP.NET 将源文件重新编译为程序集。修改应用程序中的顶级项时,应用程序中引用顶级程序集的所有其他程序集也会重新编译。

此外,修改、添加或删除应用程序已知文件夹中的某些类型的文件将导致应用程序重新启动。以下操作将导致应用程序重新启动:

从应用程序的 Bin 文件夹中添加、修改或删除程序集。

从App_GlobalResources或App_LocalResources文件夹中添加、修改或删除本地化资源。

添加、修改或删除应用程序的 Global.asax 文件。

在App_Code目录中添加、修改或删除源代码文件。

添加、修改或删除配置文件配置。

在App_WebReferences目录中添加、修改或删除 Web 服务引用。

添加、修改或删除应用程序的 Web.config 文件。

当需要重新启动应用程序时,ASP.NET 将在重新启动应用程序域并加载新程序集之前处理来自现有应用程序域和旧程序集的所有挂起请求。

HTTP 模块
ASP.NET 应用程序生命周期可通过 IHttpModule 类进行扩展。ASP.NET 包括几个实现 IHttpModule 的类,例如 SessionStateModule 类。您还可以创建自己的实现 IHttpModule 的类。

如果将模块添加到应用程序,则模块本身可以引发事件。应用程序可以使用约定modulename_eventname在 Global.asax 文件中的这些事件中订阅。例如,若要处理由 FormsAuthenticationModule 对象引发的身份验证事件,可以创建一个名为 FormsAuthentication_Authenticate 的处理程序。

默认情况下,类在 ASP.NET 中处于启用状态。所有会话事件都会自动连接为Session_event,例如Session_Start。每次创建新会话时都会引发 Start 事件。有关详细信息,请参阅 ASP.NET 会话状态概述。

参见
概念
ASP.NET 页面生命周期概述

ASP.NET 概述

ASP.NET 编译概述

其他资源
ASP.NET 和 IIS 配置