前言

ASP.NET页面运行时候,页面将经历一个生命周期,在生命周期中将执行一系列的处理步骤。包括初始化、实例化控件、还原和维护状态、运行时间处理程序代码以及进行呈现。熟悉页面生命周期非常重要,这样我们才能在生命周期的合适阶段编写代码。如果我们能在写代码的时候想着我们现在是在做生命周期的哪一步那将是非常好的。

你可能会说我不清楚还不是一样写代码,反正每次都在Page_load里面写代码 然后页面就出来了我管那么多干什么。所谓知其然如果能知其所以然岂不是更吊?我个人认为做ASP.NET B/S开发只要咱们熟悉ASP.NET页面生命周期,熟悉“请求-处理-响应模式,对于一时半儿没有触及到的细节,等真正遇到那个点再去理解它也是毫不费力的。

几个代表性的问题

在开始的时候我们先思考几个问题,看看我们在描述完页面生命周期的时候,能不能回答上这几个问题

1.为什么在服务器端能通过this.textbox1.Text获取到用户提交过来的数据?

2.Page_LoadResponse.Write("hello")查看生成的html代码原文件,hello在哪里?为什么?

3.有一个服务器端的按钮,设置了点击事件,该点击事件什么时候执行?是先执行Page_Load事件还是先执行点击事件?

4.为什么在服务器端通过this.textbox1.Text设置值后,客户端就能显示出来?

看过我上一篇博客【深入ASP.NET原理系列】--ASP.NET请求管道、应用程序生命周期、整体运行机制 童鞋可能知道,ASP.NET应用程序周期中PreRequestHandlerExecute事件与PostRequestHandlerExecute事件之间就是我们的页面生命周期了,对于aspx页面就是一系列的打造页面控件树,触发各种页面时间,对于一般处理程序ashx就是直接执行咱们开发者写的ProcessRequest方法了,对于MVC应用程序就是创建控制器工厂,创建控制器对象,调用Action那一套了。

下面主要讲述的就是ASP.NET WebForm中的页面的生命周期了。

我们用反编译工具查看Page类的ProcessRequest方法可以看见先调用了FrameworkInitializeFrameworkInitialize里面就是打造了页面控件树,然后调用了ProcessRequestMain,就开始了执行整个页面生命周期了(其实就是调用了一系列的事件方法)(可能部分图看不见右边,可在新标签页中打开图片)

1.打造页面控件树

FrameworkInitialize内部调用了_buildControlTree()方法

  

上图中左边是前台页面的代码,右边是对应 生成的打造控件树的代码。中间截取的是生成表单那一部分的代码。
下面看一张原理图

  
浏览器的DOM树是根据Html标签生成一个C语言的DOM树,而ASP.NET服务器端是用C#打造的一个控件树,也是按照DOM结构打造的。本质是一样。服务器端所有东西都加到页面对象的控件集合中去了。标签在服务器端有对应的控件对象的时候就用控件对象,没有的时候就使用LiteralControl进行封装。不管是服务器控件还是字符串标签(没有runat="server"的标签)都以控件对象的方式存在前台页面类的控件集合里面。好处就是生成前台页面的html代码的时候,只需要遍历控件集合里面的每一个控件对象的RenderControl方法,每一个控件都会调用自己的Render方法生成对应的Html字符串。那么所有控件的生成的html字符串就还原成一个页面的html代码了。  

2.触发PerformPreInit事件 

    

在所有初始化之前初始化了这个事件,这个事件主要是初始化了主题,初始化了母版页

    

 

    

3.触发InitRecursive事件

  

4.触发LoadAllState()事件

加载页面状态解析ViewState,将页面表单中的ViewState进行反Base64编码,反序列化,存在页面的ViewState属性中

    

5.触发ProcessPostData(this._requestValueCollection, true)事件

 

主要做了两件事
1)将表单里提交过来的控件数据设置给页面对象的控件树中对应控件的属性(给前面打造的控件树里面控件给值),这样在服务器端就可以拿到客户端输入的值了。
2)将表单里面提交过来的值与ViewState中控件原来的值进行比对,不同则表示要触发该控件的Change 事件,则同时将该控件放到一个集合(看源码其实就是changedPostDataConsumers)中。在后续执行过程中遍历改集合依次触发对应控件的Change事件。

6.触发LoadRecursive()事件

大名鼎鼎的Page_Load就是在这里执行的。不过是先执行页面本身的Load事件再执行页面控件的Load事件哦,这时候前面给控件赋的值,表单提交过来的数据,ViewState等等都可以使用了,IsPostBack的原理就是判断是否有name为__VIEWSTATE的数据提交过来

7.再次触发ProcessPostData(this._leftoverPostData, false)事件

这个事件我在网上看了很多人说是将第一次遗漏下来的,第一次执行ProcessPostData没有涉及到的控件进行处理,但是并没有说明哪些遗漏下来了。为什么第一次没处理了? 最后Google查到是处理我们开发者在页面的Page_Load方法中添加的控件。在Page_Load中我们可以自己创建控件对象加到页面对应的“C#DOM树中“,如:在Page_Load中写
TextBox txt = new TextBox();txt.ID ="myTxtBox";this.form1.Controls.Add(txt);
这就是把开发者自己创建的控件加在页面的form1的表单中。当然你也可以加上Change事件了创建控件的时候。执行的还是上面那两件事了。则回发的时候可以给开发者在Page_Lod中手动创建的控件还原值
    

8.触发RaiseChangedEvents事件

循环遍历changedPostDataConsumers集合中的所有控件,依次执行控件的非点击回传事件,比如文本框的改变事件等      

9.触发RaisePostBackEvent(this._requestValueCollection)事件

执行按钮点击回传事件或者验证事件,如果有多个按钮,根据回发过来的按钮的 name来判断触发哪个按钮的事件,或者触发该控件的验证事件
  

10.触发PerformPreRenderComplete事件


循环遍历控件树中所有的控件,根据每个控件生成对应的Html代码,把服务器控件渲染成普通的html控件。

11.触发事件SaveAllState事件

将服务器端ViewState集合中的内容(开发者自己加的数据或控件状态信息等)序列化然后Base64编码然后设置到客户端隐藏域__ViewState中

12.RenderControl(this.CreateHtmlTextWriter(this.Response.Output))

把要发送到客户端浏览器的内容设置到Response.Output,应用程序将它发送 到客户端浏览器。

看到这里不知道大家是否已经可以清晰地回答开篇提到的几个问题了,其实就是这些事件执行的先后顺序,页面生命周期了。”前人植树,后人乘凉了"

最后附上生命周期ProcessRequest源码  

【深入ASP.NET原理系列】--ASP.NET页面生命周期的更多相关文章

  1. ASP.NET Web 应用程序及页面生命周期

    以客户端浏览器向 ASP.NET Web 应用程序页面发送请求(Request)为起点,以浏览器收到 Web 服务器的响应(Response)为终点,这一完整的过程被称为"应用程序及页面的生 ...

  2. 【深入ASP.NET原理系列】--ASP.NET请求管道、应用程序生命周期、整体运行机制

    微软的程序设计和相应的IDE做的很棒,让人很快就能有生产力..NET上手容易,生产力很高,但对于一个不是那么勤奋的人,他很可能就不再进步了,没有想深入下去的动力,他不用去理解整个框架和环境是怎么执行的 ...

  3. ASP.NT运行原理和页面生命周期详解及其应用

    ASP.NT运行原理和页面生命周期详解及其应用 1. 下面是我画的一张关于asp.net运行原理和页面生命周期的一张详解图.如果你对具体不太了解,请参照博客园其他帖子.在这里我主要讲解它的实际应用.  ...

  4. WebForm页面生命周期及asp.net运行机制

    1.先上几张原理图着重理解: 现在针对第四副图原理进行解析: 流程: 1.浏览器发送请求 2.服务器软件(IIS)接收,它最终的目的就是为了向客户输出它请求的动态页面生成的html代码. 3.服务器不 ...

  5. [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》

    [ASP.NET MVC2 系列]      [ASP.NET MVC2 系列] ASP.Net MVC教程之<在15分钟内用ASP.Net MVC创建一个电影数据库应用程序>       ...

  6. Asp.net页面生命周期详解任我行(2)-WebForm页面生命周期WEBFORM_ASPNET控件树的生成和作用

    摘要 页面类是如何结合后台文件类生成整个页面的HTML的代码和后台输出的代码输出到浏览器中呢?这就牵扯到Asp.net页面生命周期中一个很重要的概念控件树.服务器以反射的方式创建了页面类对象 内容 我 ...

  7. ASP.net 页面生命周期

    ASP.NET 页面生命周期 Page_Preinit(); 在页初始化开始时发生 Page_Init(); 在所有控件初始化且应用外观设置后引发 Page_InitComplete(); 在页初始化 ...

  8. [转]ASP.NET应用程序生命周期趣谈(四) HttpHandler和页面生命周期

    在之前的三篇文章中,我们还算简明扼要的学习了asp.net的整个生命周期,我们知道了一个Request进来以后先去ISAPI Filter,发现是asp.net程序后又ASPNET_ISAPI.dll ...

  9. asp.net页面生命周期

    Asp.Net页面生命周期 本文转载自:http://www.cnblogs.com/xhwy/archive/2012/05/20/2510178.html 一.什么是Asp.Net页面生命周期 当 ...

随机推荐

  1. 用swift实现自动录音器

    基本介绍 自动录音与一般录音区别在:不用像微信那样按下录音-松手结束,而是根据说话声音的大小自动判断该录音和该停止的点,然后可以做到结束录音之后马上播放出来.类似于达到会说话的汤姆猫那样的效果. 在自 ...

  2. 浅谈被加壳ELF(即android的so文件)的调试

    本文只讨论如何调试被加壳的ELF文件,包括调试中的技巧运用及调试过程中可能遇到的问题的解决方法,不包含如何还原加固的DEX本文将以某加壳程序和某加固为目标. 一.ELF格式简介 ELF全称:Execu ...

  3. Android中将xml布局文件转化为View树的过程分析(上)

    有好几周没写东西了,一方面是因为前几个周末都有些事情,另外也是因为没能找到好的写作方向,或者说有些话题 值得分享.写作,可是自己积累还不够,没办法只好闷头继续研究了.这段时间一边在写代码,一边也在想A ...

  4. 个人作业week-1-14061195

    软件: 根据维基百科, The first theory about software—prior to creation of computers as we know them today—was ...

  5. 旧项目如何切换到Entity Framework Code First

    Entity Framework Code First固然是好东西,然而如果是已经存在的旧有项目,如何简单方便的使用切换呢? 这里介绍一个VS的插件Entity Framework Power Too ...

  6. 查看ORACLE的实际执行计划

    ORACLE的执行计划分为预估执行计划和实际执行计划.其中,你用Toad.PL/SQL Developer.SQL Developer.EXPLAIN PLAN FOR或者SET ATUOTRACE ...

  7. Windows服务调试小结(附Demo)

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 阅读目录 介绍 搭建环境 调试方式 Demo下载 本文版权归mephisto和博客园共有,欢迎转载,但须 ...

  8. .NET序列化的一点技巧(附Demo)

    阅读目录 介绍 详细 处理 结论 Demo下载 介绍 序列化是将对象状态转换为可保持或传输的形式的过程.序列化的补集是反序列化,后者将流转换为对象.这两个过程一起保证数据易于存储和传输. .NET F ...

  9. 单表60亿记录等大数据场景的MySQL优化和运维之道

    此文是根据杨尚刚在[QCON高可用架构群]中,针对MySQL在单表海量记录等场景下,业界广泛关注的MySQL问题的经验分享整理而成,转发请注明出处. 杨尚刚,美图公司数据库高级DBA,负责美图后端数据 ...

  10. Office——EXCEL 显示 隐藏 Ribbon 调用宏

    ==================================声明================================== 本文版权归作者所有 未经作者授权 请勿转载 保留法律追究的 ...