在网上看到这篇文章,老外写的,里面很多图片挺精致,顺带翻译过来给大家分享下,英语太次好多地方都翻不过来
ASP.NET application and page life cycle
Download source code - 4.03 KB
目录
- 简介
- 两步处理法
- 创建ASP.NET环境
- 使用MHPM事件处理请求
- 在哪些事件里我们哪些事?
- 一个简单的示范代码
- 放大ASP.NET页面事件
- 关于源码
- references
简介
在这篇文章,我们将努力弄明白从用户发送请求开始到浏览器渲染完毕过程中所发生的不同事件。所以我们要搞清楚ASP.NET请求的两个大阶段,
然后我们来将进入从不同事件来触发‘HttpHandler
’, ‘HttpModule
’和ASP.NET页面对象。在这个事件旅程中,我们要理解每一个事件所发生逻辑过程
这个电子书适合涵盖.NET中的比如WCF,WPF,WWF,ajax,Core.NET,SQL等等知识点,你可以下载相同的内容from here 或者你可以追我每天的免费课程from here.
两步处理法
从30000英尺的高度来看(From 30,000 feet level,搞不清作者是不是在戏谑), ASP.NET 请求处理分两步进行,如下,用户发送一个请求到IIS:
- ASP.NET创建一个可以处理该请求的环境,换句话说,它创建了应用程序对象,请求、形影和上下文对象来处理改请求
- 当环境创建完毕,该请求被一系列经过一系列来自于使用模块(by using modules),处理器(handlers)和页面对象的事件进行处理,为了简化,我们把这一阶段命名为MHPM(Module,Handler,page and Module event),我们一会讲详细介绍
In the coming sections, we will understand both these main steps in more detail.
创建ASP.NET环境
Step 1: 用户发送了一个请求到IIS,IIS(进程inetinfo.exe)首先检查哪一个ISAPI可以处理这个请求。这个是由文件的扩展名来确定的,例如,如果页面是.aspx的页面,那么就会通过‘aspnet_isapi.dll’ 来处理
Step 2: 假如这是对这个站点发送的第一个请求,那么一个名字叫‘ApplicationManager
’的类会创建一个应用程序域在站点运行的地方。众所周知,来自不同站点程序的应用程序域是在同一个IIS中是相互隔离的。所以如果在一个app域中存在问题,它是不会影响到其他的app域的。
Step 3: 新创建的app域创建托管环境(hosting environment),例如,‘HttpRuntime
’对象。一旦托管环境被创建,那些必须的核心ASP.NET对象比如‘HttpContext
’ , ‘HttpRequest
’ and ‘HttpResponse
’也会被创建.
Step 4: 一旦所有的ASP.NET核心对象被创建完毕,‘HttpApplication
’对象被创建来服务用户的请求,如果你的系统中包含有一个‘global.asax’文件,那么‘global.asax’文件的对象会被创建。请记住global.asax文件时内置在‘HttpApplication
’类中的。
Note: 第一次一个ASP.NET页面连接到一个app,一个新的‘HttpApplication
’实例被创建,为了最大限度提高性能,‘HttpApplication
’的实例可以重复用于多个请求
Step 5: 然后HttpApplication
对象被分配到ASP.NET核心对象来处理页面.
Step 6: HttpApplication
然后通过HTTP模块事件,处理器和页面事件来处理请求。它会触发MHPM事件来进行请求处理
Note: 想了解过多, read this.
下面的图片说明了那些内部对象模块和ASP.NET请求的关系,在最顶层是创建‘Appdomain
’的ASP.NET运行时,
‘Appdomain
’包含‘request’, ‘response’ and ‘context’ 对象的‘HttpRuntime
’
使用MHPM事件处理请求
一旦‘HttpApplication
’创建完毕,它开始处理请求了。它经历了三个不同的阶段.它在通过这些阶段,它调用不同的事件,在这些事件中,开发者可以扩展代码添加自己的逻辑到里面。
在我们继续之前,让我们搞清楚什么是‘HttpModule
’ 和 ‘HttpHandlers
’。他们帮助我们注入自定义逻辑在ASP.NET页面处理之前和之后,二者的主要区别如下:
· If you want to inject logic based in file extensions like ‘.ASPX’, ‘.HTML’, then you use ‘HttpHandler
’. In other words, ‘HttpHandler
’ is an extension based processor.
· If you want to inject logic in the events of ASP.NET pipleline, then you use ‘HttpModule
’. ASP.NET. In other words, ‘HttpModule
’ is an event based processor.
如果想了解更多,戳 here.
下面是请求处理的逻辑过程,下面展示了4个重要步骤:
Step 1(M: HttpModule): 客户请求处理开始,在ASP.NET引擎运行和创建前,ASP.NET HttpModule
提供可以注入自定义逻辑的事件,它提供了6个重要的事件你可以用在页面对象创建BeginRequest
, AuthenticateRequest
,AuthorizeRequest
, ResolveRequestCache
, AcquireRequestState
和 PreRequestHandlerExecute
之前。
Step 2 (H: ‘HttpHandler’): 当上面6个事件执行完毕,ASP.NET引擎接着触发事件,假如你的项目中有执行HttpHandler
,ASP.NET引擎将会调用ProcessRequest
事件。
Step 3 (P: ASP.NET page): 当HttpHandler
的逻辑执行,当前ASP.NET页面对象就创建完毕。当ASP.NET页面对象创建完,
一些事件被触发,我们可以在这些页面事件里编写自定义的逻辑,在ASP.NET里提供6个重要的事件我们可以编写自定义的逻辑。
页面的Init
, Load
, validate
, event
, render
and unload
.你可以用单词SILVER
来记忆这些事件,S-开始(在这个单词中没有特殊的含义),I-Init,L-Load,V-Validate,E-Event,R-Render
Step4 (M: HttpModule): 当页面对象执行完毕并从内存中卸载,HttpModule
提供了后期页面处理事件我们可以用来处理页面逻辑。
它有4个重要的后期处理事件, PostRequestHandlerExecute
, ReleaserequestState
, UpdateRequestCache
和 EndRequest
.
下面的图片诠释了刚才的过程.
在哪些事件里我们哪些事?
价值百万美元的问题来了,在某个事件里,我们该做什么?下面的表格列出了在什么事件执行哪些逻辑处理的代码。
Section |
Event |
Description |
HttpModule |
BeginRequest |
This event signals a new request; it is guaranteed to be raised on each request. |
HttpModule |
AuthenticateRequest |
This event signals that ASP.NET runtime is ready to authenticate the user. Any authentication code can be injected here. |
HttpModule |
AuthorizeRequest |
This event signals that ASP.NET runtime is ready to authorize the user. Any authorization code can be injected here. |
HttpModule |
ResolveRequestCache |
In ASP.NET, we normally use outputcache directive to do caching. In this event, ASP.NET runtime determines if the page can be served from the cache rather than loading the patch from scratch. Any caching specific activity can be injected here. |
HttpModule |
AcquireRequestState |
This event signals that ASP.NET runtime is ready to acquire session variables. Any processing you would like to do on session variables. |
HttpModule |
PreRequestHandlerExecute |
This event is raised just prior to handling control to the HttpHandler. Before you want the control to be handed over to the handler any pre-processing you would like to do. |
HttpHandler |
ProcessRequest |
Httphandler logic is executed. In this section, we will write logic which needs to be executed as per page extensions. |
Page |
Init |
This event happens in the ASP.NET page and can be used for: · Creating controls dynamically, in case you have controls to be created on runtime. · Any setting initialization. · Master pages and the settings. In this section, we do not have access to viewstate, postedvalues and neither the controls are initialized. |
Page |
Load |
In this section, the ASP.NET controls are fully loaded and you write UI manipulation logic or any other logic over here. |
Page |
Validate |
If you have valuators on your page, you would like to check the same here. |
Render |
It’s now time to send the output to the browser. If you would like to make some changes to the final HTML which is going out to the browser, you can enter your HTML logic here. |
|
Page |
Unload |
Page object is unloaded from the memory. |
HttpModule |
PostRequestHandlerExecute |
Any logic you would like to inject after the handlers are executed. |
HttpModule |
ReleaserequestState |
If you would like to save update some state variables like session variables. |
HttpModule |
UpdateRequestCache |
Before you end, if you want to update your cache. |
HttpModule |
EndRequest |
This is the last stage before your output is sent to the client browser. |
一个简单的示范代码
With this article, we have attached a sample code which shows how the events actually fire. In this code, we have created a ‘HttpModule
’ and ‘Httphandler
’ in this project and we have displayed a simple response write in all events, below is how the output looks like.
Below is the class for ‘HttpModule
’ which tracks all events and adds it to a global collection.
public class clsHttpModule : IHttpModule
{
......
void OnUpdateRequestCache(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnUpdateRequestCache");
}
void OnReleaseRequestState(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnReleaseRequestState");
}
void OnPostRequestHandlerExecute(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnPostRequestHandlerExecute");
}
void OnPreRequestHandlerExecute(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnPreRequestHandlerExecute");
}
void OnAcquireRequestState(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnAcquireRequestState");
}
void OnResolveRequestCache(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnResolveRequestCache");
}
void OnAuthorization(object sender, EventArgs a)
{
objArrayList.Add("httpModule:OnAuthorization");
}
void OnAuthentication(object sender, EventArgs a)
{
objArrayList.Add("httpModule:AuthenticateRequest");
}
void OnBeginrequest(object sender, EventArgs a)
{
objArrayList.Add("httpModule:BeginRequest");
}
void OnEndRequest(object sender, EventArgs a)
{
objArrayList.Add("httpModule:EndRequest");
objArrayList.Add("<hr>");
foreach (string str in objArrayList)
{
httpApp.Context.Response.Write(str + "<br>") ;
}
}
}
Below is the code snippet for ‘HttpHandler
’ which tracks ‘ProcessRequest
’ event.
public class clsHttpHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
clsHttpModule.objArrayList.Add("HttpHandler:ProcessRequest");
context.Response.Redirect("Default.aspx");
}
}
We are also tracking all the events from the ASP.NET page.
public partial class _Default : System.Web.UI.Page
{
protected void Page_init(object sender, EventArgs e)
{
clsHttpModule.objArrayList.Add("Page:Init");
}
protected void Page_Load(object sender, EventArgs e)
{
clsHttpModule.objArrayList.Add("Page:Load");
}
public override void Validate()
{
clsHttpModule.objArrayList.Add("Page:Validate");
}
protected void Button1_Click(object sender, EventArgs e)
{
clsHttpModule.objArrayList.Add("Page:Event");
}
protected override void Render(HtmlTextWriter output)
{
clsHttpModule.objArrayList.Add("Page:Render");
base.Render(output);
}
protected void Page_Unload(object sender, EventArgs e)
{
clsHttpModule.objArrayList.Add("Page:UnLoad");
}}
Below is how the display looks like with all events as per the sequence discussed in the previous section.
放大ASP.NET页面事件
在上面的章节,我们浏览了一个ASP.NET页面请求的完整流程。其中最重要的是章节是ASP.NET页面,我们还没有讨论它的细节,So,让我们在这一章节花费一些精力来描述一下ASP.NET页面事件的更多细节。
一些ASP.NET有2部分,一部分是在浏览器上展示的带有HTML标签的部分,另一个存放在HTML input元素上的表单的viewstate隐藏域。当页面发布,在服务器端,带有viewstate和表单数据捆绑的ASP.NET控件创建了html标签, (原文:these HTML tags are created in to ASP.NET controls with viewstate and form data tied up together on the server,这句翻译起来好别扭,自己原文理解下吧),我们可以在后台代码中获取到所有的服务器端控件,可以执行和编写自定义的逻辑然后把页面渲染到浏览器
现在,对于这些作为ASP.NET控件的可连接服务器的HTML控件,ASP.NET提供了大量的可供我们自定义逻辑的事件。我们只需要把我们所需要定义的任务或逻辑放在合适的事件里面。(原文:Now between these HTML controls coming live on the server as ASP.NET controls, the ASP.NET page emits out lot of events which can be consumed to inject logic. Depending on what task / logic you want to perform, we need to put this logic appropriately in those events.这段翻译有问题。)
Note: 大多数开发者直接使用page_load
处理所有的事情。这可不是一个好想法。So,它既要填充控件,设置view state,设置主题等等,每一件事情发生在page load。So,如果我们能把自定义逻辑按照事件自然属性的放入适当的事件中,那我们的代码看起来会更清爽些。
Seq |
Events |
Controls Initialized |
View state |
Form data |
What Logic can be written here? |
1 |
Init |
No |
No |
No |
Note: You can access form data etc. by using ASP.NET request objects but not by Server controls.Creating controls dynamically, in case you have controls to be created on runtime. Any settinginitialization.Master pages and them settings. In this section, we do not have access to viewstate , posted values and neither the controls are initialized. |
2 |
Load view state |
Not guaranteed |
Yes |
Not guaranteed |
You can access view state and any synch logic where you want viewstate to be pushed to behind code variables can be done here. |
3 |
PostBackdata |
Not guaranteed |
Yes |
Yes |
You can access form data. Any logic where you want the form data to be pushed to behind code variables can be done here. |
4 |
Load |
Yes |
Yes |
Yes |
This is the place where you will put any logic you want to operate on the controls. Like flourishing a combobox from the database, sorting data on a grid, etc. In this event, we get access to all controls, viewstate and their posted values. |
5 |
Validate |
Yes |
Yes |
Yes |
If your page has validators or you want to execute validation for your page, this is the right place to the same. |
6 |
Event |
Yes |
Yes |
Yes |
If this is a post back by a button click or a dropdown change, then the relative events will be fired. Any kind of logic which is related to that event can be executed here. |
7 |
Pre-render |
Yes |
Yes |
Yes |
If you want to make final changes to the UI objects like changing tree structure or property values, before these controls are saved in to view state. |
8 |
Save view state |
Yes |
Yes |
Yes |
Once all changes to server controls are done, this event can be an opportunity to save control data in to view state. |
9 |
Render |
Yes |
Yes |
Yes |
If you want to add some custom HTML to the output this is the place you can. |
10 |
Unload |
Yes |
Yes |
Yes |
Any kind of clean up you would like to do here. |
关于源码
This source code shows how the complete ASP.NET request cycle fires. You can download it from here.
References
I am not so smart to write this article by myself , lot of things I have plugged from the below articles.
· Read more about IIS 7.0 life cycle http://msdn.microsoft.com/en-us/library/bb470252.aspx
· Intercepting filters http://msdn.microsoft.com/en-us/library/ms998536.aspx
· Explains how to implement Httphandlers and moduleshttp://msdn.microsoft.com/enus/library/system.web.httpapplication.aspx
· Httphandlers and Httpmodules :- http://www.15seconds.com/Issue/020417.htm
· Implementing security using modules and handlers http://joel.net/articles/asp.net2_security.aspx
· Difference between Httpapplication and global.asaxhttp://codebetter.com/blogs/karlseguin/archive/2006/06/12/146356.aspx
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)