• Asp.Net生命周期系列六


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

    话说我们今天的重中之重:页面生命周期,说的就是Page类在处理页面的过程中都发生了哪些事件,而这些事件又是按照什么顺序发生的。ASP.NET的页面生命周期跟我们之前的理论讲解完全不同,它具有非常强大的实用性,所以我想通过一个小例子来进行解释和说明,以便让大家看起来更清晰和容易理解。因为Page类的ProcessRequest方法实现非常的复杂,我把代码反编译过来给大家看我觉得也没什么意义,所以我就着重给大家看一下整个页面的事件是以何种顺序被引发的,以及在这些事件中,我们能做什么。在这个过程中,我们主要关注如下问题:

    1,    事件的执行顺序

    2,    控件何时被初始化(我们什么时候能用它)

    3,    ViewState何时可用

    4,    更改MasterPageTheme

    5,    在各个事件中还能干什么工作

    按照如下步骤建立示例:

    一,我们创建一个website

    二,加入两个MasterPage分别为site.mastermap.master,分别在上面加一个label进行说明:this is site/map master page.

    三,分别加入两个themeBlueSkinRedSkin,分别对button的背景色进行设置,一个是Blue,另外一个是Red

    四,default页面中加入两个label和一个button

    五,Default页面代码如下:

     

    private int step = 1;
      2     private string GetEventName(string eventName)
      3     {
      4         step += 1;
      5         return eventName;
      6     }
      7 
      8     protected override void OnPreInit(EventArgs e)
      9     {
     10         base.OnPreInit(e);
     11         Response.Write(GetEventName("pre init event, this is the " + step + "th step!"));
     12         //lblMessage.Text = "on pre init";
     13 
     14         this.MasterPageFile = "map.master";
     15         this.Theme = "BlueSkin";
     16         if (lblMessage2 == null)
     17         {
     18             Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
     19         }
     20         else
     21         {
     22             Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
     23         }
     24         if(this.ViewState.Count>0)
     25         {
     26             Response.Write("ViewState can be used here, the ID is "+ViewState["ID"].ToString());
     27         }
     28 
     29         Response.Write("<br/>");
     30     }
     31     protected override void OnInit(EventArgs e)
     32     {
     33         if (lblMessage2 == null)
     34         {
     35             Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
     36         }
     37         else
     38         {
     39             Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
     40         }
     41         base.OnInit(e);
     42       
     43         Response.Write(GetEventName("init event, this is the " + step + "the step!   "));
     44         if (lblMessage2 == null)
     45         {
     46             Response.Write("<span style='color:red;'>Server control has not been initialed on pre init</span>");
     47         }
     48         else
     49         {
     50             Response.Write("<span style='color:red;'>Server control has been initialed here</span>");
     51         }
     52         if (this.ViewState.Count > 0)
     53         {
     54             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
     55         }
     56         Response.Write("<br/>");
     57 
     58         //this.MasterPageFile = "map.master";
     59         //this.Theme = "BlueSkin";
     60     }
     61     protected override void OnInitComplete(EventArgs e)
     62     {
     63         base.OnInitComplete(e);
     64         Response.Write(GetEventName("init complete event, this is the " + step + "th step!"));
     65         if (this.ViewState.Count > 0)
     66         {
     67             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
     68         }
     69         else
     70         {
     71             Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
     72         }
     73         Response.Write("<br/>");
     74     }
     75     protected override void OnPreLoad(EventArgs e)
     76     {
     77         if (this.ViewState.Count > 0)
     78         {
     79             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
     80         }
     81         else
     82         {
     83             Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
     84         }
     85         base.OnPreLoad(e);
     86         Response.Write(GetEventName("pre load event, this is the " + step + "th step!"));
     87         if (this.ViewState.Count > 0)
     88         {
     89             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
     90         }
     91         else
     92         {
     93             Response.Write("<span style='color:red;'>ViewState can not be used here</span>");
     94         }
     95         Response.Write("<br/>");
     96     }
     97     protected void Page_Load(object sender, EventArgs e)
     98     {
     99         Response.Write(GetEventName("page load system provided, this is " + step + "th step!"));
    100         if (this.ViewState.Count > 0)
    101         {
    102             Response.Write("<span style='color:red;'>ViewState can be used here, the ID is " + ViewState["ID"].ToString() + "</span>");
    103         }
    104         Response.Write("<br/>");
    105     }
    106 
    107     protected override void OnLoadComplete(EventArgs e)
    108     {
    109         base.OnLoadComplete(e);
    110         Response.Write(GetEventName("on load complete event, this is the " + step + "th step!<br/>"));
    111     }
    112 
    113     protected override void OnPreRender(EventArgs e)
    114     {
    115         base.OnPreRender(e);
    116         Response.Write(GetEventName("pre render event, this is the " + step + "th step!<br/>"));     
    117     }
    118 
    119     protected override void OnPreRenderComplete(EventArgs e)
    120     {
    121         base.OnPreRenderComplete(e);
    122         Response.Write(GetEventName("pre render complete event, this is the " + step + "th step!<br/>"));
    123     }
    124 
    125     protected override void OnSaveStateComplete(EventArgs e)
    126     {
    127        
    128         base.OnSaveStateComplete(e);
    129         Response.Write(GetEventName("sae state complete event, this is the " + step + "th step!<br/>"));
    130     }
    131 
    132     protected override void Render(HtmlTextWriter writer)
    133     {
    134         base.Render(writer);
    135         Response.Write(GetEventName("render function, this is the " + step + "th step!<br/>"));
    136     }
    137 
    138     protected override void OnUnload(EventArgs e)
    139     {
    140         if (this == null)
    141         {
    142             string aaa = string.Empty;
    143         }
    144         if (lblMessage2 == null)
    145         {
    146             string ga = string.Empty;
    147         }
    148         base.OnUnload(e);
    149         if (this == null)
    150         {
    151  
    152         }
    153     }
    154 
    155     protected override void OnLoad(EventArgs e)
    156     {
    157         base.OnLoad(e);
    158         Response.Write(GetEventName("page load we created, this is the " + step + "th step!<br/>"));
    159     }
    160     protected void btnSubmit_Click1(object sender, EventArgs e)
    161     {
    162         ViewState["ID"] = "12345";
    163         Response.Write(GetEventName("button control click event, this is the " + step + "th step!<br/>"));
    164     }

     

    执行结果:

    七,代码分析

    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里面的ThemeMasterPage的设置是生效了的,我们可以在PreInit里设置ThemeMasterPage,而在其它任何位置设置这两个东西都将抛出异常(看我注视掉的代码)

    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类。如果您不喜欢研究那么深入,我想我这几篇文章应该可以对您有些帮助。

     

     

  • 相关阅读:
    easyui多选与接收不一致解决方案
    PEP8规范总结
    python2与python3的区别
    双下方法(魔术方法内置方法)
    文件操作
    抽象类,接口类,归一化设计,多态,鸭子类型
    html
    数据库的初识
    boby标签中相关标签
    爬虫介绍
  • 原文地址:https://www.cnblogs.com/skm-blog/p/3219528.html
Copyright © 2020-2023  润新知