接触ASP.NET 已经很久了,“所见即所得”的开发方式吸引了很多人,让很多多年从事ASP.NET开发的开发人员对于ASP.NET的认识还停留在“拖控件”的状态。有一句话说得好,优秀的程序员绝对不会说:“这个程序可以很好地运行,但是我却不知道他怎么运行的。”乐于并善于探究现象背后的本质应该就是码农和工程师之间的区别吧?本着这种精神,最近我深入学习了下ASP.NET Application 的生命周期,HttpHandle,HttpModule等概念。今天是2014年的最后一天,写这样一篇博客来纪念我的2014.
ASP.NET 应用程序处理用户请求的整个流程大致分为两个步骤:1)创建处理请求的环境 2)通过HttpHandle,HttpModule及其相应的事件来处理 User Request
接下来,我们将深入探讨每个步骤里面具体做了些什么。
1.创建运行环境
1)用户发起请求到IIS.IIS首先根据请求资源的类型判断哪个ISAPI扩展能否处理当前的请求。判断的依据是请求的文件的扩展名。比如,用户请求的是.aspx文件,这个请求会被发送给aspnet_isapi.dll进行处理。
2)如果当前的请求是该Web Application 的第一次请求,那么ApplicationManager类的对象会创建供web Appliction运行的环境-应用程序域(Application Domain),通常称作AppDomain.AppDomain提供了一种运行在IIS上的多个Web Application(WebSite)之间的隔离机制,这种隔离机制确保了多个Web Application互相独立运行而不互相影响,例如,一个Web Application 发生了问题导致应用程序崩溃,另外一个Web Application不会受到影响。
3)新创建的AppDomain创建Web Application的运行环境-HttpRuntime对象。一旦运行环境建立成功,处理Http请求的核心ASP.NET对象,如HttpContext,HttpRequest,HttpResponse就会被创建。
4)一旦处理Http请求的核心ASP.NET对象创建成功,HttpApplication就会被创建起来处理请求。如果系统中包含Global.asax文件,那么Global.asax中的对象也会被创建起来。注意,Global.asax是继承自HttpApplication类的。
Note:当ASP.NET 页面第一次被附加到Web Application的时候,一个新的HttpApplication对象就会被创建,为了提升ASP.NET Web Application的性能,这个对象会在处理Use Reqest的过程中多次重用。
5)HttpApplication对象会注入给核心的ASP.NET对象来处理页面。
6)HttpApplication对象通过HttpModule,HttpHandle及页面的事件来处理用户请求。
上图展示了User Request的流程,下图展示了ASP.NET核心对象的包含关系。
2.处理请求
通过HttpModule,HttpHandler,ASP.NET Page and Mobule Event(这四者简称MHPM)来处理用户请求。一旦HttpApplication对象创建成功,HttpApplication对象就开始处理请求,处理的过程要经过三个阶段,HttpModule,Page,HttpHandler。在这三个阶段里,会激发不同的事件,开发者可以扩展或自定义这些事件的响应逻辑。关于HttpModule及HttpHandler的概念,这里不做赘述,二者在应用上最大的区别是:如果希望增加对新的请求类型的处理,就自定义HttpHandler;如果扩展对已有的请求类型的处理逻辑,就自定义HttpModule。
在User Request请求管道中,有很多事件会触发,这些事件触发的示意图如下:
下面一张示意图是展示每个处理事件中的详细细节:
下面一个列表是更加详细的描述:
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:
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. |
ASP.NET 页面也有很多事件处理的过程,详细内容如下:
Seq | Events | Controls Initialized | View state Available | Form data Available | 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 setting |
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. |
最后有一张图归纳了处理的顺序:
本章节到此为止,欢迎关注下一个章节的内容。