Asp.net页面生命周期详解服务器处理请求详细过程
前言
百度了一下才知道,传智的邹老师桃李满天下呀,我也是邹老师的粉丝,最开始学习页面生命周期的时候也是看了邹老师的视频。
本人是参考了以下前辈的作品,本文中也参合了本人心得,绝非有意盗版,旨在传播,最主要是日后在下也可以参考一下,原版出处如下:
概念
所谓的页面生命周期说通俗一点,就是浏览器有请求,服务器处理请求并生成HTML代码所执行的一系列的事件方法。
概括知识点
1.服务器与浏览器之间的交互:通过Scoket
2.服务器与浏览器交互语法:Http协议
3.服务器与浏览器交互目的:获取服务器资源(html,js,img,css..)
4.服务器要做的事就是想尽办法满足浏览器的需求,所以一旦浏览器请求的是动态页面的时候,服务器就要创建页面类对象并执行里面的一系列的事件与方法,并将生成的html页面代码返回给浏览器.
页面生命周期事件
1.PreInit:
- 检查IsPostBack 属性
- 创建或重新创建动态控件
- 动态设置主控页
- 动态设置Theme属性
- 读取或者设置配置文件属性值
- 设置控件的默认值(UniqueId等)
- 动态设置Master Page
注意:如果请求是回发请求,刚控件的值尚未从视图状态还原,如果在此阶段设置控件属性,则其值可能会在下一事件中被重写。
2. Init:
在所有控件都已经初始化且已应用所有外观设置后引发,使用该事件来读取或初始化控件属性
3.InitComplete:
由Page对象引发。使用该事件来处理要求先完成所有初始化工作的任务。
4.PreLoad:
如果需要在Load事件之前对页或者控件执行处理,则使用该事件。
在Page引发该事件后,它会为自身和所有 控件加载视图状态,然后会处理Request实例包括的任何回发数据。
5.Load:
在Page上调用OnLoad事件方法,然后以递归方式对每个子控件执行相同操作,如此循环往复,直到加载完页面和所有控件为止
6.控件事件:
使用这些事件来处理特定控件事件,如Button控件的Click事件或TextBox控件的TextChanged事件
注意:在回发请求中,如果页包含验证程序控件,刚需要在执行任何处理之前检查Page和各个验证控件的IsValid属性
7.LoadComplete:
对需要加载页上的所有其他控件的任务使用该事件
8.PreRender:
在该事件发生之前:
- Page对象会针对每个控件和页调用 EnsureChildControls
- 设置了DataSourceID属性的每个数据绑定控件会调用DataBind方法
页上的每个控件都会发生PreRender事件。使用该事件对页或其控件的内容进行最后更改
9.SaveStateComplete
在该事件发生前,已对每个控件保存了ViewState。将忽略此时对页或控件进行的任何更改。使用该事件执行满足以下条件的任务:要求已经保存了视图状态,但未对控件进行任何更改。
10.Render
这不是事件:在处理的这个阶段,Page对象会在每个控件上调用此方法。所有 ASP.NET Web服务器控件都有一个用于写出发送给浏览器的控件标记的Render方法。如果创建自定义控件,则通常要重写此方法以输出控件的标记。不过如果自定义控件只合并标准的 ASP.NET Web服务器控件,并不合并自定义标记,则不需要重写Render方法。用户控件自动合并呈现,因此不需要在代码中显式呈现该控件。
11:UnLoad
该事件首先针对每个控件发生,继而针对该页发生,在控件中,使用该事件对特定控件执行最后清理,如关闭控件特定数据库连接,清理输出缓存。对于页自,使用该事件来执行最后的清理工作,如关闭打开 的文件和数据库连接,或完成日志记录或其他特定请求任务。
学习目的
有些人讲,webform/asp.net方面的技术,有些研究得太深,在现实开发中其实不一定有太大的价值。我极力的反驳这句话。据我个人了解与使用情况,学习页面生命周期有以下几个好处:
1.开发Asp.net自定义控件与用户控件
2.利用HttpModule注册页面生命周期中HttpApplication中用于处理请求的19个事件管道所对外公布的一系列的事件方法
3.编写页面周期事件方法(如:Page_PreLoad,Page_Load,Page_Init...)等等一系列的事件,且这些方法并不会因为我们的编写而覆盖原有的事件方法,请大家放心使用,不过在上述所有事件前面要加上Page_。
注意事项
1.所有控件都有生命周期,我们在前面就已经了解到Page类是继承Control类的,而我们所有的服务器控件也都是继承Control类的
2.虽然Init与Load都在每个控件上以递归方式发生,但它们的发生顺序相反,每个子控件的Init事件(还有UnLoad事件)在为其容器引发相应的事件之前发生(由上到下)。但是,容器的Load事件是在其子控件的Load事件之前 发生(由上到下)的。
3.从Page类继承过来的时候,除了可以处理由页引发的事件以外,还可以重写页的基类中的方法,例如可以重写页的InitializeCulture方法,以便动态设置区域性信息,注意,在使用Page_事件语法创建事件处理程序时,将隐式调用基实现,因此无须在方法中调用它。例如使用Page_Load方法始终会调用基类的OnLoad方法,如果使用overrider重写了页的OnLoad方法,则必须显式调用基类的OnLoad方法,如base.OnLoad()以运行基实现。
浏览器与服务器的通信过程
通信过程:
当服务器运行正常的情况下,客户端(浏览器) 向服务器端发送请求时,服务器端负责监听的套接字(socket),监听到有连接请求后,会为该客户端建立一个用于通信的套接字与客户端进行通信。当用户在浏览器向服务器发送请求时,浏览器会按照双方都约定好的网络传输层http协议,将请求转换成符合Http协议的请求报文。然后通过设备按照TCP协议发送到服务器。在服务器端接收到请求报文后。会按照Http协议对报文进行解析。若请求的内容为静态的数据,服务器端直接将被请求的数据,按照Http协议生成响应报文后返回给浏览器。浏览器然后解析收到的报文。将页面显示到浏览器窗口。(注:最开始仅是显示一个html 框架。经过多次请求。将CSS样式,图片………逐一的加载进来形成一个完整的页面。这个过程,有多次的交互通信。当通信结束后会把用来通信的套接字销毁,因为http协议是一种无状态的通信。这样减轻了服务器的压力)
当浏览器向客户端发送的请求为动态的。那么服务器(IIS)发现处理不了这种后缀名的文件时,会通过映射表到。响应实现了接口的可扩展程序asp.net_isapi.dll, 然后asp.net_isapi.dll,又将请求转交给网站程序处理.网站程序调用
httpRuntime类的processRequest方法来处理:
1.此类会分析接收到的请求报文.将请求报文封装到名称为httpWorkerRequest的类的属性中(便于其它地方以用).
2.创建HttpContext对象.这个对象是当前所请求报文的上下文环境.它包含了所有的请求数据.其中有两个最重要类的对象:http.Request和http.Response. 在httpRequest对象中又包含了两个属性.Form(通过表单请求的数据参数).Querystring(通过URL传递的数据参数); 通过索引器,可以找到参数的值. 在httpResponse 对象中有一个TextWriter对象.在它里面保存的是被请求的页面在执行过程中要向浏览器输出的数据.可以通过write 方法对其进行输出给浏览器。
3.通过HttpApplicationFactory类的的一个静态方法。来为每个请求创建一个单独的httpApplication对象。在创建之前HttpApplicationFactor会到HttpApplication池中查看,有没有空闲的。若有直接用。没有的时候才创建新的HttpApplication。
4.在httpApplication里运行己转换成接口IhttpHandler 的通过反射被请求页面对象的ProcessRequest 方法.
方法执行过程如下:先执行httpApplication中的processRequest方法。在此方法中包含了要按照先后顺序执行的19个委托事件 当在执行到第8个事件(PostMapRequestHandler)的时候就开始创建被请求页面对象,并得到请求处理程序,在执行到第11个事件(PreRequestHandlerExecute)后。就执行被创建的请求页面对象的ProcessRequest方法。
HttpApplication 通信管理(用于给HttpModule注册使用的19个事件委托)
HttpModule被称为Filter过滤器。用户可以利用HttpModule来给这19个委托事件来注册方法,完成需求,比如说可以在AcquireRequestState中验证是否登录呀,权限验证等
详情请查看:HttpModule实现用户身份验证
如果不清楚HttpModule可以查看:HttpModule的认识
页面生命周期详细过程
其实页面生命周期里面还有很东西,如PageHandlerFactory等等这些东东也够吃一壶的,发现我每走到一个领域,发现我要学的东西实在是太多太多啦,总感觉自己所学的东西只是沧海一粟,走过了这道坎,又是一片海洋,我只能呐喊:生命永不止息,学海无涯。
摘抄之http://www.cnblogs.com/xuyubing/p/3363934.html