2024年2月7日发(作者:)
.NET (C#) Internals: 应用程序与页面生命周期(意译)
1、引言
2、两个处理步骤
2.1、创建环境
2.2、用触发的MHPM事件处理请求
3、什么事件中应该做什么
4、示例代码
5、深入页面事件
1、引言
这篇文章我们将试图理解,从用户发送一个请求直到请求呈现到浏览器发生的事件的差异。因此,我们首先将介绍解请求的两个概括的步骤,接下来我们将介绍‘HttpHandler’,‘HttpModule’和页面对象发出的事件的差异。随着我们的事件旅程,我们将理解这些事件的逻辑。
2、两个处理步骤
请求处理可以总结为如下所示的两个处理步骤。用户发送一个请求到IIS:创建处理请求的环境。换句话说,创建应用程序对象、request、response和context对象去处理请求。
一旦环境已经创建,请求通过使用modules、handlers和page对象的一系列事件处理。为了简化可以称为MHPM(module、handler、page、module event),我们将在后面详细讨论。
图1、请求处理的两个步骤
在接下来的各节,我们将知道更多关于这两个步骤的细节。
2.1、创建环境
step 1:用户发送一个请求到IIS。IIS首先检查哪个ISAPI扩展可以处理这个请求,这取决于请求的文件扩
展名。举例来说,如果请求页面是‘.ASPX’,它将被传送到‘aspnet_’来处理。
step 2:如果这是www站点的第一个请求,ApplicationManager类将创建一个应用程序域,www站点运行于其中。我们都知道在同一个IIS上,两个web应用程序的应用程序域是独立的(隔离的)。因此一个应用程序域中问题不会的影响到其它应用程序域。
step 3:新建的应用程序域创建宿主环境,如HttpRuntime对象。一旦宿主环境被创建,必要的核心对象如HttpContext、HttpRequest和HttpRespone对象也被创建。
step 4:一旦所有的核心对象被创建,HttpApplication对象将被创建去处理请求。如果系统中有文件,文件对象将被创建。
【注意】:文件继承自HttpApplication类;第一次页面连接到应用程序,一个HttpApplication新实例将被创建。为了最大化性能,HttpApplication实例可能被多个请求重用。
step 5:接下来HttpApplication对象分配给核心对象来处理页面。
step 6:然后HttpApplication通过HttpContext、HttpRequest和HttpRespone事件开始处理请求。它触发MHPM事件处理请求。【更多细节】:/en-us/library/
图2、创建环境
下图解释了请求的内部对象模型。最高层是运行时,它已经创建一个应用程序域(AppDomain),相应地有HttpRuntime包括request、respone、context对象。
图3、请求的内部对象模型
2.2、用触发的MHPM事件处理请求
一旦创建了HttpApplication,它开始处理请求,它经历3个不同的部分HttpModule、Page、HttpHandler。随着它移动到这些部分,将调用不同的事件,开发人员可以扩展和定制同一逻辑。在我们前进之前让我们了解什么是HttpModule和HttpHandlers。他们帮组我们在页处理的前后注入自定义逻辑。他们之间的主要差别是:
(1)如果你想要注入的逻辑是基于像‘.ASPX’、‘.HTML’这样的文件扩展名,使用HttpHandler。换句话说HttpHandler是基于处理器的扩展。
(2)如果你想在管道事件中注入逻辑,使用HttpModule。换言之是基于处理器的事件。
你可以点这了解他们之间更多的差异。下面是怎样处理请求的逻辑流。有四个重要的步骤MHPM,解释如下:
Step 1(M HttpModule):客户端请求处理开始。引擎开始和创建HttpModule发出事件(你可以注入定制逻辑)之前,有6个重要事件你可以使用:BeginRequest、AuthenticateRequest、AuthorizeRequest、ResolveRequestCache、AcquireRequestState和PreRequestHandlerExecute。
Step 2(H HttpHandler):一旦上面6个事件触发,引擎将调用ProcessRequest事件,即使你已经在项目中执行了HttpHandler。
Step 3(P page):一旦HttpHandler逻辑执行, page对象被创建。 page对象被创建,许多事件被触发,你可以在这些页面事件中写我们自定义的逻辑。有6个重要事件给我们提供占位,在页中写逻辑:Init、Load、Validate、Event、Render、Unload。你可以记住单词SILVER来记这些事件,S-Start(没有任何意义,仅仅是为了形成一个单词),I(Init)、L(Load)、V(Validate)、E(Event)、R(Render)。
Step 4(M HttpModule):一旦页面对象执行了且从内存中卸载,HttpModule提供发送页面执行事件,它们可用于注入自定义post-处理逻辑。有4个重要的post-处理事件,PostRequestHandlerExecute、PostRequestState、UpdateRequestCache、EndRequest。
下图展示了上面的过程。
3、什么事件中应该做什么
下面的表格展示了什么事件中做什么逻辑或代码。
Section
HttpModule
HttpModule
HttpModule
HttpModule
Event
BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequest
有。
此事件标志运行时准备验证用户。任何身份验证代码都可以在此注入。
此事件标志运行时准备授权用户。任何授权代码都可以在此注入。
在中我们通常使用OutputCache指令做缓存。在这个事件中,运行时确定是否能够从缓存中加载页面,而不是从头开始生成。任何缓存的具体活动可以被注入这里。
Description
此事件标志着一个新的请求,他保证在每个请求中都
HttpModule
HttpModule
HttpHandler
Page
AcquireRequestState
PreRequestHandlerExecute
ProcessRequest
Init
此事件标志着运行时准备获得会话变量。可以对会话变量做任何你想要的处理。
恰好在 开始执行事件处理程序前发生。可以预处理你想做的事。
HttpHandler逻辑被执行。在这个部分我们将为每个页面扩展名写需要的逻辑。
此事件发生在页面且可以用来:
1、动态地创建控件,如果你一定要在运行时创建控件;
2、任何初始化设置
3、母版页及其设置
在这部分中我们没有获得viewstate、postedvalues及已经初始化的控件。
在这部分控件完全被加载且在这里你可以写UI操作逻辑或任何其他逻辑。
如果在页面上你有验证器,你同样想在这里检查。
是时候将输入发送到浏览器。如果你想对最终的HTML做些修改,你可以在这里输入你的HTML逻辑。
Page
Page
Page
Load
Validate
Render
Page Unload
页面对象从内存中卸载。
HttpModule PostRequestHandlerExecute
可以注入任何你想要的逻辑,在处理程序执行之后。
HttpModule
HttpModule
HttpModule
ReleaseRequestState
UpdateRequestCache
EndRequest
想保存更新某些状态变量,如会话变量。
在结束之前是否更新你的缓存。
这是将输出发送到客户端浏览器之前的最后一个阶段。
4、示例代码
点击下载代码,示例代码展示了事件是怎样触发的。代码中我们创建了一个HttpModule和HttpHandler,且我们显示一个简单的响应在所有的事件中。下面是HttpModule类,跟踪所有的事件且添加到全局集合。
HttpModule类
下面是HttpHandler的代码片段,它跟踪ProcessRequest事件。
HttpHandler代码片段
我们也追踪页面的所有事件。
下面显示上面讨论的所有事件的执行顺序:
5、深入页面事件
在前面部分我们已经知道页面请求的整体事件流,但是我们没有详细讨论,因此本节我们将深入了解。任何页面有2个部分,一个是显示在浏览器上的页面,它有HTML标记、viewstate形式的隐藏值、HTML inputs上的数据。当页面被发送时,在服务器上这些HTML标记被创建到控件且viewstate和表单数据捆绑在一起。一旦你得到这些服务器控件的后台代码,你可以执行和写你自己的逻辑和呈现返回给浏览器。
现在这些HTML控件在服务器上作为控件,页面发出一些事件,我们可以注入自己的逻辑。根据任务/你要执行的逻辑,我们需要把这些逻辑放入适当的事件中。
【注意】:大部分开发者直接使用Page_Load方法执行一切,这不是一个好的方法。因此,不是填充控件、设置viewstate、应用主题等一切都发生在页面加载上。因此,如果我们能在适当的事件中放入逻辑,将真正使你的代码干净。、
Seq Events
控件初始化
Viewstate可用
1 Init No No No
注意:你可以通过使用请求对象访问表单数据等,但是不是通过服务器控件。
动态地创建控件,如果你一定要在运行时创建;任何初始化设置;母版页及其设置。在这部分中我们没有获得viewstate、postedvalues及已经初始化的控件。
2 Load View State Not
guaranteed
3
4
PostBackdata
Load
Not
guaranteed
Yes Yes Yes
Yes
Yes Not
你可以访问View State及任何同步逻辑,你希guaranteed
望viewstate被推倒后台代码变量可以在这里完成。
Yes
捏可以访问表单数据。任何逻辑,你希望表单数据被推倒后台代码变量可以在这里完成。
在这里你可以放入任何你想操作控件的逻辑,如从数据库填充combox、对grid中的数据排序等。这个事件,我们可以访问所有控件、viewstate、发送的值。
5
6
Validate
Event
Yes
Yes
Yes
Yes
Yes
Yes
如果你的页面有验证器或者你想为你的页面执行验证,那就在这里做吧。
如果这是通过点击按钮或下拉列表的改变的一个回发,相关的事件将被触发。与事件相关的任何逻辑都可以在这里执行。
7 Pre-render Yes Yes Yes
如果你想对UI对象做最终的修改,如改变属性结构或属性值,在这些控件保存到ViewState表单数据可用
什么逻辑可以写在这里?
之前。
8
9
10
Save ViewState
Render
Unload
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
一旦对服务器控件的所有修改完成,可以保存控件数据到View State。
如果你想添加一些自定义HTML到输出,可以在这里完成。
做任何你想做的清理工作。
.NET Framework 4 -
1 Application Life Cycle Overview for IIS 5.0 and 6.0
This topic outlines the life cycle of applications, listing important life-cycle events and describing how
code that you write can fit into the application life cycle. The information in this topic applies to IIS 5.0 and
IIS 6.0. For information about the application life cycle in IIS 7.0, see Application Life Cycle
Overview for IIS 7.0.
Within , several processing steps must occur for an application to be initialized and process
requests. Additionally, is only one piece of the Web server architecture that services requests made
by browsers. It is important for you to understand the application life cycle so that you can write code at the
appropriate life cycle stage for the effect you intend.
Application Life Cycle in General
The following table describes the stages of the application life cycle.
Stage Description
User requests an The life cycle of an application starts with a request sent by a browser to the Web
application server (for applications, typically IIS). is an ISAPI extension under the
resource from the Web server. When a Web server receives a request, it examines the file-name extension of
Web server. the requested file, determines which ISAPI extension should handle the request, and then
passes the request to the appropriate ISAPI extension. handles file name
extensions that have been mapped to it, such as .aspx, .ascx, .ashx, and .asmx.
Note
If a file name extension has not been mapped to , will not receive the
request. This is important to understand for applications that use authentication.
For example, because .htm files are typically not mapped to , will not
perform authentication or authorization checks on requests for .htm files. Therefore, even
if a file contains only static content, if you want to check authentication, create
the file using a file name extension mapped to , such as .aspx.
Note
If you create a custom handler to service a particular file name extension, you must map
the extension to in IIS and also register the handler in your application's
file. For more information, see HTTP Handlers and HTTP Modules Overview.
receives When receives the first request for any resource in an application, a class named
the first request
for the
application.
ApplicationManager creates an application domain. Application domains provide
isolation between applications for global variables and allow each application to be
unloaded separately. Within an application domain, an instance of the class named
HostingEnvironment is created, which provides access to information about the
application such as the name of the folder where the application is stored.
The following diagram illustrates this relationship:
also compiles the top-level items in the application if required, including
application code in the App_Code folder. For more information, see "Compilation Life
Cycle" later in this topic.
core
objects are
created for each
request.
After the application domain has been created and the HostingEnvironment object
instantiated, creates and initializes core objects such as HttpContext,
HttpRequest, and HttpResponse. The HttpContext class contains objects that are specific
to the current application request, such as the HttpRequest and HttpResponse objects.
The HttpRequest object contains information about the current request, including cookies
and browser information. The HttpResponse object contains the response that is sent to
the client, including all rendered output and cookies.
An
HttpApplication
After all core application objects have been initialized, the application is started by
creating an instance of the HttpApplication class. If the application has a file,
object is assigned instead creates an instance of the class that is derived from the
to the request
HttpApplication class and uses the derived class to represent the application.
Note
The first time an page or process is requested in an application, a new instance of
HttpApplication is created. However, to maximize performance, HttpApplication instances
might be reused for multiple requests.
When an instance of HttpApplication is created, any configured modules are also created.
For instance, if the application is configured to do so, creates a
SessionStateModule module. After all configured modules are created, the
HttpApplication class's Init() method is called.
The following diagram illustrates this relationship:
The request is The following events are executed by the HttpApplication class while the request is
processed by the processed. The events are of particular interest to developers who want to extend the
HttpApplication
pipeline.
1. Validate the request, which examines the information sent by the browser and
determines whether it contains potentially malicious markup. For more
information, see ValidateRequest() and Script Exploits Overview.
2. Perform URL mapping, if any URLs have been configured in the
UrlMappingsSection section of the file.
3. Raise the BeginRequest() event.
4. Raise the AuthenticateRequest() event.
5. Raise the PostAuthenticateRequest() event.
6. Raise the AuthorizeRequest() event.
7. Raise the PostAuthorizeRequest() event.
8. Raise the ResolveRequestCache() event.
9. Raise the PostResolveRequestCache() event.
10. Based on the file name extension of the requested resource (mapped in the
application's configuration file), select a class that implements IHttpHandler to
process the request. If the request is for an object (page) derived from the Page
class and the page needs to be compiled, compiles the page before
creating an instance of it.
11. Raise the PostMapRequestHandler() event.
12. Raise the AcquireRequestState() event.
13. Raise the PostAcquireRequestState() event.
14. Raise the PreRequestHandlerExecute() event.
15. Call the ProcessRequest(HttpContext) method (or the asynchronous version
System#Web#IHttpAsyncHandler#BeginProcessRequest(HttpContext,
AsyncCallback, Object)) of the appropriate IHttpHandler class for the request. For
example, if the request is for a page, the current page instance handles the
request.
16. Raise the PostRequestHandlerExecute() event.
17. Raise the ReleaseRequestState() event.
18. Raise the PostReleaseRequestState() event.
HttpApplication class.
19. Perform response filtering if the Filter() property is defined.
20. Raise the UpdateRequestCache() event.
21. Raise the PostUpdateRequestCache() event.
22. Raise the EndRequest() event.
23. Raise the PreSendRequestHeaders() event.
24. Raise the PreSendRequestContent() event.
Life Cycle Events and the file
During the application life cycle, the application raises events that you can handle and calls particular methods
that you can override. To handle application events or methods, you can create a file named in the
root directory of your application.
If you create a file, compiles it into a class derived from the HttpApplication class, and
then uses the derived class to represent the application.
An instance of HttpApplication processes only one request at a time. This simplifies application event
handling because you do not need to lock non-static members in the application class when you access them.
This also allows you to store request-specific data in non-static members of the application class. For example,
you can define a property in the file and assign it a request-specific value.
automatically binds application events to handlers in the file using the naming
convention Application_event, such as Application_BeginRequest. This is similar to the way that page
methods are automatically bound to events, such as the page's Page_Load event. For details, see
Page Life Cycle Overview.
The Application_Start and Application_End methods are special methods that do not represent
HttpApplication events. calls them once for the lifetime of the application domain, not for each
HttpApplication instance.
The following table lists some of the events and methods that are used during the application life cycle. There
are many more events than those listed, but they are not commonly used.
Event or
method
Description
Application_Start Called when the first resource (such as a page) in an application is requested.
The Application_Start method is called only one time during the life cycle of an
application. You can use this method to perform startup tasks such as loading data into
the cache and initializing static values.
You should set only static data during application start. Do not set any instance data
because it will be available only to the first instance of the HttpApplication class that is
created.
Application_event Raised at the appropriate time in the application life cycle, as listed in the application life
cycle table earlier in this topic.
Application_Error can be raised at any phase in the application life cycle.
Application_EndRequest is the only event that is guaranteed to be raised in every request,
because a request can be short-circuited. For example, if two modules handle the
Application_BeginRequest event and the first one throws an exception, the
Application_BeginRequest event will not be called for the second module. However, the
Application_EndRequest method is always called to allow the application to clean up
resources.
Init() Called once for every instance of the HttpApplication class after all modules have been
created.
Dispose() Called before the application instance is destroyed. You can use this method to manually
release any unmanaged resources. For more information, see Cleaning Up Unmanaged
Resources.
Application_End Called once per lifetime of the application before the application is unloaded.
Compilation Life Cycle
When the first request is made to an application, compiles application items in a specific order. The
first items to be compiled are referred to as the top-level items. After the first request, the top-level items are
recompiled only if a dependency changes. The following table describes the order in which top-level
items are compiled.
Item
App_GlobalResources
Description
The application's global resources are compiled and a resource assembly is
built. Any assemblies in the application's Bin folder are linked to the
resource assembly.
App_WebResources Proxy types for Web services are created and compiled. The resulting Web
references assembly is linked to the resource assembly if it exists.
Profile properties defined in
the file
App_Code
If profile properties are defined in the application's file, an
assembly is generated that contains a profile object.
Source code files are built and one or more assemblies are created. All code
assemblies and the profile assembly are linked to the resources and Web
references assemblies if any.
The application object is compiled and linked to all of the previously
generated assemblies.
After the application's top level items have been compiled, compiles folders, pages, and other items
as needed. The following table describes the order in which folders and items are compiled.
Item
App_LocalResources
Description
If the folder containing the requested item contains an
App_LocalResources folder, the contents of the local
resources folder are compiled and linked to the global
resources assembly.
Individual Web pages (.aspx files), user
controls (.ascx files), HTTP handlers (.ashx
files), and HTTP modules (.asmx files)
Themes, master pages, other source files
Compiled as needed and linked to the local resources
assembly and the top-level assemblies.
Skin files for individual themes, master pages, and other
source code files referenced by pages are compiled when the
referencing page is compiled.
Compiled assemblies are cached on the server and reused on subsequent requests and are preserved across
application restarts as long as the source code is unchanged.
Because the application is compiled on the first request, the initial request to an application can take
significantly longer than subsequent requests. You can precompile your application to reduce the time
required for the first request. For more information, see How to: Precompile Web Sites.
Application Restarts
Modifying the source code of your Web application will cause to recompile source files into
assemblies. When you modify the top-level items in your application, all other assemblies in the application
that reference the top-level assemblies are recompiled as well.
In addition, modifying, adding, or deleting certain types of files within the application's known folders will
cause the application to restart. The following actions will cause an application restart:
Adding, modifying, or deleting assemblies from the application's Bin folder.
Adding, modifying, or deleting localization resources from the App_GlobalResources or
App_LocalResources folders.
Adding, modifying, or deleting the application's file.
Adding, modifying, or deleting source code files in the App_Code directory.
Adding, modifying, or deleting Profile configuration.
Adding, modifying, or deleting Web service references in the App_WebReferences directory.
Adding, modifying, or deleting the application's file.
When an application restart is required, will serve all pending requests from the existing application
domain and the old assemblies before restarting the application domain and loading the new assemblies.
HTTP Modules
The application life cycle is extensible through IHttpModule classes. includes several classes
that implement IHttpModule, such as the SessionStateModule class. You can also create your own classes that
implement IHttpModule.
If you add modules to your application, the modules themselves can raise events. The application can
subscribe to in these events in the file by using the convention modulename_eventname. For
example, to handle the Authenticate() event raised by a FormsAuthenticationModule object, you can create a
handler named FormsAuthentication_Authenticate.
The SessionStateModule class is enabled by default in . All session events are automatically wired up
as Session_event, such as Session_Start. The Start() event is raised each time a new session is created. For
more information, see Session State Overview.


发布评论