上篇说到当一个Http请求流到HttpHandler这里时才开始对它的处理,那么一个请求经过HttpHandler之后, 到底怎么对它处理呢,也就是说HttpHandler会触发哪些事件,触发的顺序如何,我们可以在此中间做些什么?

话说我们今天的重中之重:页面生命周期,说的就是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页面代码如下:

;
       private string GetEventName(string eventName)
       {
           step += ;
           return eventName;
       }

       protected override void OnPreInit(EventArgs e)
       {
          base.OnPreInit(e);
          Response.Write(GetEventName("pre init event, this is the " + step + "th step!"));
          //lblMessage.Text = "on pre init";

          this.MasterPageFile = "map.master";
          this.Theme = "BlueSkin";
          if (lblMessage2 == null)
          {
              Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
          }
          )
          {
              Response.Write("ViewState can be used here, the ID is "+ViewState["ID"].ToString());
          }

          Response.Write("<br/>");
      }
      protected override void OnInit(EventArgs e)
      {
          if (lblMessage2 == null)
          {
              Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
          }
          base.OnInit(e);

          Response.Write(GetEventName("init event, this is the " + step + "the step!   "));
          if (lblMessage2 == null)
          {
              Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
          }
          )
          {
              Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
          }
          Response.Write("<br/>");

          //this.MasterPageFile = "map.master";
          //this.Theme = "BlueSkin";
      }
      protected override void OnInitComplete(EventArgs e)
      {
          base.OnInitComplete(e);
          Response.Write(GetEventName("init complete event, this is the " + step + "th step!"));
          )
          {
              Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
          }
          Response.Write("<br/>");
      }
      protected override void OnPreLoad(EventArgs e)
      {
          )
          {
              Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
          }
          base.OnPreLoad(e);
          Response.Write(GetEventName("pre load event, this is the " + step + "th step!"));
          )
          {
              Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
          }
          else
          {
              Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
          }
          Response.Write("<br/>");
      }
      protected void Page_Load(object sender, EventArgs e)
      {
          Response.Write(GetEventName("page load system provided, this is " + step + "th step!"));
         )
         {
             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
         }
         Response.Write("<br/>");
     }

     protected override void OnLoadComplete(EventArgs e)
     {
         base.OnLoadComplete(e);
         Response.Write(GetEventName("on load complete event, this is the " + step + "th step!<br/>"));
     }

     protected override void OnPreRender(EventArgs e)
     {
         base.OnPreRender(e);
         Response.Write(GetEventName("pre render event, this is the " + step + "th step!<br/>"));
     }

     protected override void OnPreRenderComplete(EventArgs e)
     {
         base.OnPreRenderComplete(e);
         Response.Write(GetEventName("pre render complete event, this is the " + step + "th step!<br/>"));
     }

     protected override void OnSaveStateComplete(EventArgs e)
     {

         base.OnSaveStateComplete(e);
         Response.Write(GetEventName("sae state complete event, this is the " + step + "th step!<br/>"));
     }

     protected override void Render(HtmlTextWriter writer)
     {
         base.Render(writer);
         Response.Write(GetEventName("render function, this is the " + step + "th step!<br/>"));
     }

     protected override void OnUnload(EventArgs e)
     {
         if (this == null)
         {
             string aaa = string.Empty;
         }
         if (lblMessage2 == null)
         {
             string ga = string.Empty;
         }
         base.OnUnload(e);
         if (this == null)
         {

         }
     }

     protected override void OnLoad(EventArgs e)
     {
         base.OnLoad(e);
         Response.Write(GetEventName("page load we created, this is the " + step + "th step!<br/>"));
     }
     protected void btnSubmit_Click1(object sender, EventArgs e)
     {
         ViewState[";
         Response.Write(GetEventName("button control click event, this is the " + step + "th step!<br/>"));
     }

执行结果:

七,代码分析

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生命周期系列六的更多相关文章

  1. Asp.Net生命周期系列三

    上文讲到了HttpRunTime主要做了三个事情,我们先回忆一下. 第一:雇佣了项目经理(HttpApplication). 第二:建立了HttpModule列表,项目经理(HttpRunTime)就 ...

  2. Asp.Net生命周期系列四

    上回我们说的当一个Http请求来到HttpModule这里的时候,Asp.Net内部并未对这个Http请求做出任何的处理,我们可以对这个Http请求添加一些我们需要的信息,以方便我们控制这个Http请 ...

  3. Asp.Net生命周期系列五

    如果您看了我的前四篇文章,应该知道目前Http请求已经流到了HttpModule这个程序员手中了,而且我们可以注册自己的HttpModule并且可以在里面注册一些事件来控制这个Http请求,但是到目前 ...

  4. Asp.Net生命周期系列二

    在上回书开始的时候我们提到博客园的IIS看了一眼我的请求后就直接交给ASP.NET去处理了,并且要求ASP.NET处理完之后返回HTML以供展示. 那么我们不仅要问: 1,    IIS肯定是没有眼睛 ...

  5. Asp.Net复习篇之Asp.Net生命周期与Asp.Net页的生命周期

    Asp.Net生命周期与Asp.Net页的生命周期是一个比较重要的话题,有时可能似乎知道一些,但又说不出个所以然,而且时常把这两个概念混淆.现在也是该好好理清思路,把这两个概念搞懂. Asp.Net生 ...

  6. ASP.NET生命周期详解

    最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...

  7. ASP.NET生命周期详解 [转]

    最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...

  8. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(六)

    使用 HttpApplication 对象 ASP.NET 框架中的许多类都提供了许多很方便的属性可以直接映射到 HttpContext 类中定义的属性.这种交叠有一个很好的例子就是 HttpAppl ...

  9. 【IHttpHandler】ASP.NET 生命周期

    对由 Microsoft® Internet 信息服务 (IIS) 处理的 Microsoft® ASP.NET 页面的每个请求都会被移交到 ASP.NET HTTP 管道.HTTP 管道由一系列托管 ...

随机推荐

  1. scikit-learn Adaboost类库使用小结

    在集成学习之Adaboost算法原理小结中,我们对Adaboost的算法原理做了一个总结.这里我们就从实用的角度对scikit-learn中Adaboost类库的使用做一个小结,重点对调参的注意事项做 ...

  2. 一个前端引用Facebook评论插件案例

    最近公司海外的同事提了一个新的需求:那就是将Facebook的评论系统接入到公司海外网站的资讯详情页. 下面做一个简单的介绍: 首先我们登录到Facebook开发者平台:然后进入评论插件系统(http ...

  3. inline、block、inline-block的区别

    http://www.cnblogs.com/KeithWang/p/3139517.html

  4. php_access_ADOConn 备忘

    1.咕~~(╯﹏╰)b 各种乱码. 2.本来是MFC+Access 用msado15.dll写的系统,闲的想用php改改. Demo.php <meta http-equiv="Con ...

  5. Windows Office key 持续更新地址

    微软 Windows  Office 系列序列号,每日都有更新,上面显示的基本都可用,包括MAK及Retail Key. Windows 10   http://textuploader.com/52 ...

  6. java总结第二次(剩余内容)//类和对象1

    7.成员变量和局部变量 成员变量:在类中定义,用来描述对象将要有什么 局部变量:在类的方法中定义,在方法中保存临时数据 区别:作用域不同 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类内 ...

  7. 【转】Hibernate利用@DynamicInsert和@DynamicUpdate生成动态SQL语句

    原文链接:http://www.cnblogs.com/quanyongan/p/3152290.html 最近在使用Hibernate4中,发现两个很有奥秘的注解 @DynamicInsert 和  ...

  8. 学习Slim Framework for PHP v3 ( 二)

    昨天说到能够成功将本地的URL通过在index.php 中添加get(pattern,clouser)路由到指定的处理类中,处理后(这里指存入数据库中),然后返回response在浏览器中显示. 昨天 ...

  9. spring的组成

    ① Spring Core:核心容器,BeanFactory提供了组件生命周期的管理,组件的创建,装配,销毁等功能 SpringContext:ApplicationContext,扩展核心容器,提供 ...

  10. Oracle配置

    1.安装Oracle11g--->通过Database Configuration Assistant创建新数据库 建数据库注意记住数据库名和SID,安装最后一步解锁scott[密码填tiger ...