欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET页面生命周期

程序员文章站 2022-04-25 18:32:27
一、 什么是ASP.NET页面的生存周期 所谓的页面生存周期,指的是一个ASP.NET页面对象从初始化到销毁经过的步骤。在通常情况下我们在浏览器地址栏中输入网址查看页面时,浏览器则会向服务器端(IIS)发送一个Request请求,IIS就会判断发送过来的请求页面,完全识别HTTP页面处理程序类后,一 ......

 

一、     什么是asp.net页面的生存周期

所谓的页面生存周期,指的是一个asp.net页面对象从初始化到销毁经过的步骤。在通常情况下我们在浏览器地址栏中输入网址查看页面时,浏览器则会向服务器端(iis)发送一个request请求,iis就会判断发送过来的请求页面,完全识别http页面处理程序类后,一旦某个请求对应到一个asp.net 页面时,一个直接或间接继承自system.web.ui.page类型的对象开始初始化,并且开始执行页面生存周期中的所有步骤。

而每一个asp.net page页都有2个部分,即显示部分和逻辑部分:

一个部分是在浏览器中进行显示的部分,即我们平时在浏览器中看见的一切,它包含了html标签、viewstate形式的隐藏域以及在html input中的数据。当这个页面被提交到服务器的时候,这些html标签会被创建到asp.net控件之中,并且viewstate还会和表单数据绑定在一起。另一个部分是在.cs结尾的文件中的进行业务逻辑操作的部分,服务器中下载数据和服务器控件后,可以根据已有数据撰写自己的逻辑代码。

 ASP.NET页面生命周期

 

前台代码和后台代码关联关系在前台页面的最顶端位置:

 ASP.NET页面生命周期

 

 

autoeventwireup: 指示是否自动启用页事件,表示是否自动地将页面的事件和相应的方法绑定到一起,一般设为false

codefile: 指示后台代码文件。

inherits: 继承类,定义供页继承的代码隐藏类。可以是从 page 类派生的任何类。

 

二、     为什么要了解asp.net页面的生命周期

明白了页面生命周期,及其中事件发生的顺序,以及事件发生时控件的状态,就能找到合适的接入点来植入你的程序逻辑,也能有助于我们对程序调试中发生问题的地方的定位。换言之,把逻辑处理放在 pageload事件中执行并不一定是最优选择。

 

三、     看图说话

  1.  页面请求过程图

   ASP.NET页面生命周期

        2.    报文请求流程如下图所示:

      ASP.NET页面生命周期

 

 

 

四、     页面生命周期事件

  1. 页请求:页请求发生在页面生命周期开始之前,用户请求页面时,asp.net将确定是否需要分析和编译页。
  2. 开始:在开始阶段,将设置页属性,如request和response。在此阶段,页面还将确定请求是回发请求还是新请求,并设置ispostback属性。
  3. 页初始化(preinit 、 init 、initcomplete):在初始化期间可以使用页中的控件,并设置控件的id属性,设置主题,引用母版页,跟踪记录viewstate。
  4. 加载(loadstate、processpostdata、preload、load、processpostdata):反序列化viewstate,判断首次加载,不是则执行processpostdata(第一次)事件将表单中的数据加载到控件中,然后再load事件中进行逻辑处理,处理完毕后执行processpostdata(第二次)事件将load中提交至表单的数据加载至控件中。
  5. 验证:在验证期间,将调用所有的验证程序控件的validate,此方法将设置各个验证程序控件和页的isvalidate属性。
  6. 回发事件处理(changedevent、postbackevent):这里首先会比较viewstate中的数据和页面上一次回传的数据,觉得哪些时间需要被触发,这里的时间是逐一被触发的,但顺序将无法确定。然后会查看是否触发post back事件,该时间也就是页面提交的事件。可处理dropdownlist用于viewstate可能造成的changed异常事件
  7. 呈现(savestate、savestatecomplete、render):首先页面会编码保存所有的viewstate , 然后将其潜入到页面的一个隐藏空间中。接着转换所有的控件标签并生成页面html,并发回客户端。
  8. 卸载:完全呈现页,并将页面发送到客户端,准备对其该页后,将调用卸载。此时将卸载页属性并执行清理。

 

        一般情况下执行步骤为以下:

序号

事件

工作内容

1

onpreinit

1. 检查 ispostback 属性来确定是不是第一次处理该页。

2. 创建或重新创建动态控件。

3. 动态设置主控页。

4. 动态设置 theme 属性。

5. 读取或设置配置文件属性值。   

备注:如果请求是回发请求,则控件的值尚未从视图状态还原。如果在此阶段设置控件属性,则其值可能会在下一事件中被重写。

2

oninit

在所有控件都已初始化且已应用所有外观设置后引发。使用该事件来读取或初始化控件属性。

3

oninitcomplete

由 page 对象引发。使用该事件来处理要求先完成所有初始化工作的任务。

4

onpreload

1. 如果需要在 load 事件之前对页或控件执行处理,请使用该事件。

2. 在 page 引发该事件后,它会为自身和所有控件加载视图状态,然后会处理 request 实例包括的任何回发数据。

5

onload

1. page 在 page 上调用 onload 事件方法,然后以递归方式对每个子控件执行相同操作,如此循环往复,直到加载完本页和所有控件为止。

2. 使用 onload 事件方法来设置控件中的属性并建立数据库连接。

6

changedevent

(控件事件)

1. 用这些事件来处理特定服务器控件事件,如 button 控件的 click 事件等。 

备注:在回发请求中,如果页包含验证程序控件,请在执行任何处理之前检查 page 和各个验证控件的 isvalid 属性。

7

onloadcomplete

对需要加载页上的所有其他控件的任务使用该事件。

8

onprerender

在这个事件发生之后,执行数据绑定操作。

9

onsavestatecomplete

1. 在该事件发生前,已针对页和所有控件保存了 viewstate。将忽略此时对页或控件进行的任何更改。

2. 使用该事件执行满足以下条件的任务:要求已经保存了视图状态,但未对控件进行任何更改。

3. 所有事件绑定之后执行该方法

10

render

1. 该步骤不通过编程操作,它不是事件;在处理的这个阶段,page 对象会在每个控件上调用此方法。所有 asp.net web 服务器控件都有一个用于写出发送给浏览器的控件标记的 render 方法。

2. 如果创建自定义控件,通常要重写此方法以输出控件的标记。不过,如果自定义控件只合并标准的 asp.net web 服务器控件,不合并自定义标记,则不需要重写 render 方法。有关更多信息,请参见开发自定义 asp.net 服务器控件。

3. 用户控件(.ascx 文件)自动合并呈现,因此不需要在代码中显式呈现该控件。

11

onunload

1. 该事件首先针对每个控件发生,继而针对该页发生。在控件中,使用该事件对特定控件执行最后清理,如关闭控件特定数据库连接。

2. 对于页自身,使用该事件来执行最后清理工作,如:关闭打开的文件和数据库连接,或完成日志记录或其他请求特定任务。

备注在卸载阶段,页及其控件已被呈现,因此无法对响应流做进一步更改。如果尝试调用方法(如 response.write 方法),则该页将引发异常。

 

结合事件说明和下列图形我们可以看清楚asp.net 管线处理请求流程(包含 aspx 页面生命周期)和事件(event)发生的顺序和所处管道

ASP.NET页面生命周期

 

 最后:

 

 

ASP.NET页面生命周期

号外可以通过下列代码查看页面生命周期的执行顺序(点击事件再load事件后执行):

using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.ui;
using system.web.ui.webcontrols;

public partial class index : system.web.ui.page
{

    static int count = 1;
     
    //0
    protected override void onpreinit(eventargs e)
    {
        
           
        //配置下app_themes中的主题,应用母版页
        base.onpreinit(e);
        response.write("第" + count + "步:" + "----onpreinit <br/>");
        count++;
    }

    //1
    protected override void oninit(eventargs e)
    {
        //将应用的themes应用给控件,递归的触发子空间的init方法
        base.oninit(e);
        response.write("第" + count + "步:" + "----oninit <br/>");
        count++;
    }

    //2
    protected override void oninitcomplete(eventargs e)
    {
        //应用母版页,打开viewsstate的追踪
        base.oninitcomplete(e);
        response.write("第" + count + "步:" + "----oninitcomplete <br/>");
        count++;
    }
    //3
    protected override void onpreload(eventargs e)
    {

        //它的调用标示着页面进入加载状态,在该事件中,为自身和所有控件加载视图状态,然后会处理request实例包含所有会发数据 
        base.onpreload(e);
        response.write("第" + count + "步:" + "----onpreload <br/>");
        count++;
    }

 

  
    //4
    protected override void onload(eventargs e)
    {
        //这个事件可以处理回发,视图状态,themes,子控件都已经初始化完毕,所以可以添加逻辑状态。
        //值得注意的是,任何页面的load顺序是先自己,再子控件,如:一个aspx页面被调用load事件,先加载本身,然后再加载如母版页、用户控件、第三方服务器控件等等
        base.onload(e);
        response.write("第" + count + "步:" + "----onload <br/>");
        count++;
    }
  
    //5
    protected override void onloadcomplete(eventargs e)
    {
        //初始化完成,所有的控件均已经初始化完毕,所有themes都已经应用
        base.onloadcomplete(e);
        response.write("第" + count + "步:" + "----onloadcomplete <br/>");
        count++;
    }

    //6
    protected override void onprerender(eventargs e)
    {
        //该事件处理准备呈现的一些工作。如:对设置了datasource的控件进行databind,通常,我们可以再这个事件上动态修改某些控件的值
        base.onprerender(e);
        response.write("第" + count + "步:" + "----onprerender <br/>");
        count++;
    }

    protected override void onunload(eventargs e)
    {

        base.onunload(e);

    }




    protected void unnamed1_click(object sender, eventargs e)
    {
        base.onprerender(e);
        response.write("第" + count + "步:" + "----unnamed1_click <br/>");
        count++;
    }
}