[转]ASP.NET应用程序生命周期趣谈(四) HttpHandler和页面生命周期
在之前的三篇文章中,我们还算简明扼要的学习了asp.net的整个生命周期,我们知道了一个Request进来以后先去ISAPI Filter,发现是asp.net程序后又ASPNET_ISAPI.dll这个ISAPI Extension来进行处理。在ASPNT_ISAPI创建了Worder Process后,在管道中经过HttpModule的处理来到HttpHander的手中。
我们知道P_Handler程序员使用“乾坤大挪移”对页面进行了处理后又通过管道中的HttpModule把response返回给了客户端。
那么,这么
l 所谓的“乾坤大挪移”到底是个什么功夫呢?
l P_Handler又是如何被调用如何消亡的呢?
l 我们自己是否也可以创建HttpHandler呢?
l HttpHandler和我们常用的.ashx又是什么关系呢?
我们就通过今天的简单讲述让大家对这些过程有个大致的了解。
从字面上我们也可以看出,HttpHandler就是handle http(request)的,就像程序员,就是(做)程序的人员一样,所以P_Handler就是个典型的HttpRequest处理人员。我们也知道IHttpHandler接口,它就像是一个认证,任何通过了IHttpHandler认证(实现了这个接口)的人员(handler),都可以处理HttpRequest。这个认证主要有两个内容(方法):1,ProcessRequest;2,IsReusable。
ASP.NET默认有很多个Handler,它们处理了各式各样的asp.net文件,例如.config,.cs,.aspx等等。通过路径C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config找到web.config文件我们可以发现系统预定义的httphandler,因为太多在这就不一一列举。
通过<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="true" />我们可以知道我们项目中的web.config文件为什么不能访问了,原来是被 HttpForbiddenHandler给屏蔽了,我估计它是直接返回了一个错误,这样我们就不能访问这些资源,同样的,.sitemap, .asax, ..cs, .csproj等等我们熟悉的项目中的文件都是使用HttpForbiddenHandler来屏蔽掉的。
而但是通过<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="true" />我们也可以发现原来.aspx是通过PageHandlerFactory来处理的。那么PageHandlerFactory又是什么东西呢?
通过反编译PageHandlerFactory我们可以看到:
Code
这个page handler的工厂通过GetHandler得到了一个IHttpHandler,这个Handler是什么呢?答案就在GetHandlerHelper方法中:
代码
我们可以清楚的看到,这个方法返回了一个Page,wow,原来Page类就是处理.aspx文件的HttpHandler啊,看到Page类的定义:
public class Page : TemplateControl, IHttpHandler
{
}
我们更是确信无疑:System.Web.UI.Page就是处理.aspx页面的那个程序员P_Handler。这种程序员很平凡,却是不可或缺的,因为他们承担着一线的大量工作任务。而PageHandlerFactory就是专门培训这种处理页面的程序员的培训机构。这种培训机构很多,也就培养了各种各样的Handler,而我们自己也可以创建自己的培训机构,培训自己的HttpHandler,只要通过IHttpHandlerFactory这个认证(接口实现)就可以了。Page类是我们最常用的P_Handler程序员,它就像.net初级程序员一样普遍,只不过它不像我们这样什么都会,它只处理页面(因为它在一个大公司,微软啊,分工多明确啊)。
微软有程序员,我们也可以有,那么接下来我们就自己创建一个HttpHandler,我们用它来Handler我们定义的后缀名.godspeed文件。这个过程分为三步:
首先,我们创建一个实现了IHttpHandler的类
然后,在web.config文件中添加一行文字以便让server知道该如何处理.godspeed后缀名文件
最后,我们在IIS中映射我们的新后缀名到asp.net,好让IIS可以把这个文件传给ASP.NET进行处理并返回我们期望的结果。好,开始做。
1, 创建名为TestCustomHttpHandler的网站
2, 添加test.godspeed文件到网站中
3, 创建GodSpeedHttpHandler.cs文件,代码如下:
4, 配置web.config
<handlers>
<add name="GodSpeedHttpHandler" verb="*" path="*.godspeed" type="MyHandlers.GodSpeedHttpHandler "/>
</handlers>
5, 映射到IIS和asp.net
6, 访问test.godspeed
re
多简单啊 各位看官可是看明白了?不明白没关系,欢迎回复和拍砖。
而我们常用的ashx也一种非常简单的handler,它通常用来处理不需要回传的任务,比如生成动态图片等等,园子里有很多这样的示例,在这里就不详述了。
那么我们之前提到Page类只处理页面,它也是我们最最常用的,最最重要的P_Handler程序员,它究竟是如何工作呢?它的工作对我们的日常开发又有什么影响呢?在下一篇文章中我将着重讲解页面生命周期—也就是Page类的ProcessRequest都引发了哪些事件以及在这些事件中我们能做些什么进行深入的探讨。
话说我们今天的重中之重:页面生命周期,说的就是Page类在处理页面的过程中都发生了哪些事件,而这些事件又是按照什么顺序发生的。ASP.NET的页面生命周期跟我们之前的理论讲解完全不同,它具有非常强大的实用性,所以我想通过一个小例子来进行解释和说明,以便让大家看起来更清晰和容易理解。因为Page类的ProcessRequest方法实现非常的复杂,我把代码反编译过来给大家看我觉得也没什么意义,所以我就着重给大家看一下整个页面的事件是以何种顺序被引发的,以及在这些事件中,我们能做什么。在这个过程中,我们主要关注如下问题:
1, 事件的执行顺序
2, 控件何时被初始化(我们什么时候能用它)
3, ViewState何时可用
4, 更改MasterPage和Theme
5, 在各个事件中还能干什么工作
按照如下步骤建立示例:
一,我们创建一个website
二,加入两个MasterPage分别为site.master和map.master,分别在上面加一个label进行说明:this is site/map master page.
三,分别加入两个theme为BlueSkin和RedSkin,分别对button的背景色进行设置,一个是Blue,另外一个是Red
四,在default页面中加入两个label和一个button
五,Default页面代码如下:
六,执行结果:
七,代码分析
a) 从执行结果我们可以看到,事件的执行顺序为:
i. PreInit
ii. Init
iii. InitComplete
iv. PreLoad
v. Load
vi. Control Event(if they have)
vii. LoadComplete
viii. PreRender
ix. PreRenderComplete
x. SaveStateComplete
xi. Render
xii. Unload
b) 从结果中我们也可以看到,在PreInit事件发生后控件还没有被初始化,也就是我们还不能使用。而在Init刚刚发生的时候已经可以使用了。也就是说,控件初始化发生在PreInit之后Init之前。总而言之,我们关心的是我们最早可以在Init事件里对页面server端控件进行操控。
c) 关于ViewState,本示例也清晰的显示出它在Init Complete之后还是不能使用,而在PreLoad刚刚发生的时候,就已经可以使用了。
d) 通过对比Default.aspx页面的配置我们知道,在PreInit里面的Theme和MasterPage的设置是生效了的,我们可以在PreInit里设置Theme和MasterPage,而在其它任何位置设置这两个东西都将抛出异常(看我注视掉的代码)
e) 其它的事件:
Load: 这个事件可能是大家最熟悉的了。需要注意的是,Page对象会递归的调用子控件的onload事件直到页面和所有的子控件被加载完成。这个事件主要用来设置控件属性的值,建立数据库连接(通常不这么做)。
Control events: 这个就不多说了,主要是处理控件的事件,例如click。这也就让我们明白了每次我们click一个Button的时候,实际上是要先去执行load事件然后才执行click事件的,一般我们用!IsPostBack来判断一下从而避免执行不必要的加载逻辑。
LoadComplete: 页面所有的控件都被加载以后执行,暂时没有想到用来干什么。。。
PreRender: 在HTML被生成之前这是最后一个事件。每一个页面中的控件都有PreRender的过程。在这里对将要输出的HTML结果进行最后一次修改。
SaveStateComplete: 在这个时间发生之前,已经保存了所有控件和页面的,任何对page或者控件的改动都不会产生左右。暂时没想到用来干啥。
Render: 它不是一个事件而是一个方法。工作就是把HTML写回客户端浏览器。
UnLoad: 页面中的每一个控件都会发生这件事。在控件中,使用这个事件来做清理工作,例如关闭数据库连接等。对与页面本身也是做清理工作,例如关闭打开的文件和数据库连接,或者结束日志或者其它指定的工作。
f) 关于Unload事件,它实际上做的是销毁前的工作。在Unload事件发生以后,Page类被卸载和销毁,所以page类的字段值也就消失了,而我们通常也是使用在SaveStateComplete之前保存的ViewState来存储哪些我们想要存储的page里的数据。HttpRuntime做了销毁Page的动作,同样也是它创建的Page这个handler,现在我们知道原来不是HttpApplication雇佣了P_Handler, HttpApplication只是使用了它而已,真正雇佣(创建)并解雇(销毁)P_Handler的是老板HttpRuntime。
整个ASP.NET生命周期基本结束,如果大家想更深入的了解其中内情,请反编译System.Web.HttpRuntime类。如果您不喜欢研究那么深入,我想我这几篇文章应该可以对您有些帮助。
我并不打算就此停手,接下来我还将会围绕ASP.NET生命周期和大家进一步深入探知iis6中的最重要的改进—Application Pool的奥秘和重要的HttpModule—-SessionStateModule。在这些都结束以后,我将接着跟大家学习ASP.NET在IIS7中的变化及相应的知识,欢迎大牛指导和拍砖,谢谢。
相关示例代码:
自定义HttpHandler和PageLifeCycle示例代码.zip
[转]ASP.NET应用程序生命周期趣谈(四) HttpHandler和页面生命周期的更多相关文章
- [转]ASP.NET应用程序生命周期趣谈(三) HttpModule
在之前的文章中,我们提到过P_Module(HttpModule)这个能干的程序员哥们儿,它通过在项目经理HttpApplication那里得到的授权,插手整个应用程序级别的事件处理.所有的HttpM ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](四)
前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)>,我们完成了: * 引用SqlSugar * ...
- [转]ASP.NET应用程序生命周期趣谈(五) IIS7瞎说
Ps:建议初学者在阅读本文之前,先简要了解一下之前的几篇文章,以便于熟悉本文提到的一些关于IIS6的内容,方便理解.仅供参考. PS:为什么叫瞎说呢?我觉得自己理解的并不到位,只能是作为一个传声筒,希 ...
- [转]ASP.NET应用程序生命周期趣谈(一)
这几天一直在看ASP.NET应用程序生命周期,真是太难了,我理解起来费了劲了,但偏偏它又是那么重要,所以我希望能给大家带来一篇容易理解又好用的文章来帮助学习ASP.NET应用程序生命周期.这篇就是了. ...
- [转]ASP.NET应用程序生命周期趣谈(二)
在上回书开始的时候我们提到博客园的IIS看了一眼我的请求后就直接交给ASP.NET去处理了,并且要求ASP.NET处理完之后返回HTML以供展示. 那么我们不仅要问: 1, IIS肯定是没有眼睛 ...
- ASP.Net请求处理机制初步探索之旅 - Part 4 WebForm页面生命周期
开篇:上一篇我们了解了所谓的请求处理管道,在众多的事件中微软开放了19个重要的事件给我们,我们可以注入一些自定义的业务逻辑实现应用的个性化设计.本篇,我们来看看WebForm模式下的页面生命周期. ( ...
- .net学习笔记---IIS 处理模型及ASP.NET页面生命周期
本文是基于IIS6的处理模型. 当一个客户端页面访问IIS试图获取一些信息的时候,发生了什么事情?一个请求在通过了HTTP管道后又发生了什么?本文主要是描述这两个过程,即IIS处理asp.net请求和 ...
- Asp.net页面生命周期详解任我行(3)-服务器处理请求详细过程
前言 百度了一下才知道,传智的邹老师桃李满天下呀,我也是邹老师的粉丝,最开始学习页面生命周期的时候也是看了邹老师的视频. 本人是参考了以下前辈的作品,本文中也参合了本人心得,绝非有意盗版,旨在传播,最 ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)
前言 Hi,大家好,我是Rector 时间飞逝,一个星期又过去了,今天还是星期五,Rector在图享网继续跟大家分享系列文本:一步一步创建ASP.NET MVC5程序[Repository+Autof ...
随机推荐
- win7,Mindmanager2012使用模板时弹出Runtime error R6025解决方法
Mindjet.MindManager2012.v10.0在应用个别模板时提示"参数错误",然后自动关闭. 解决办法: 如果是win7系统,可以进入C:\Users\(用户名)\A ...
- MEF学习
一. 什么是MEF MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置. 扩 ...
- 前端如何正确选择offer,到底选哪个?
文章背景:来自于一次线上交流,当时回答感觉比较粗糙,做个阶段性的总结,也分享给其它朋友. 当时的题目是,共2个offer,如何选择: 1. 美团外卖前端 2. 京东深圳前端研发(只有通过邮件,还有收到 ...
- JS中给正则表达式加变量
前不久同事询问我js里面怎么给正则中添加变量的问题,遂写篇博客记录下. 一.字面量 其实当我们定义一个字符串,一个数组,一个对象等等的时候,我们习惯用字面量来定义,例如: var s = &quo ...
- [PHP源码阅读]array_push和array_unshift函数
在PHP中,在数组中添加元素也是一种很常用的操作,分别有在数组尾部和头部添加元素,看看PHP内部是如何实现数组插入的操作. 我在github有对PHP源码更详细的注解.感兴趣的可以围观一下,给个sta ...
- Memcached简介
在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法.其通过记录某部分计算结果来尝试避免再次执行得到该结果所需要的复杂计算,从而提高了服务的运行效率. 除了能够提高服务的运行效 ...
- To Java程序员:切勿用普通for循环遍历LinkedList
ArrayList与LinkedList的普通for循环遍历 对于大部分Java程序员朋友们来说,可能平时使用得最多的List就是ArrayList,对于ArrayList的遍历,一般用如下写法: p ...
- ASP.NET MVC Model元数据(五)
ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...
- C++11网络编程
Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...
- 压缩SWF文件大小!减少40%体积!
使用FlashBuild作为IDE的痛苦是显著的!如果开发的项目比较大,那么卡顿.崩溃.白屏是常事,使用别的IDE开发如Sublime.FlashDevelop.IDEA等,然后再用mxmlc编译出 ...