ASP.NET页面生命周期与优化

         作为一个ASP.NET开发,特别是进行ASP.NET控件模型的开发,了解个掌握ASP.NET页面生命周期是非常必要的,这有助于我们更加灵活的控制页面,以我们需要的方式编程开发。ASP.NET页运行时,此页会经历一个又一个的事件链,每个事件链中执行不同的行为,这所有的行为共同组成我们所需要的页面。

ASP.NET控件模型

         在此模型中,微软将基于ASP.NET控件模型的开发看做是一个又一个的控件,如同我们在绘画时,不是拿着笔在一张白纸上作画,而更像是在玩拼图游戏,我们只需要经各个部分拼接好,让这些拼图共同来构成一张画。我们的Page就像个被抽象了的容器,我们需要在玩拼图的过程中将需要的版块拿进来,并放在合适的地方。然后一切的一切控件什么TextBox,Button,DropDownList,DataList再如同什么MasterPage,UserControl均是我们玩拼图游戏时将可能运用到得“图片”。

         ASP.NET控件模式是微软的一个创举,他们提出了一种全新的变成思想,从而大大降低了web开发的门槛,使得入门更加容易

         然而进一步,微软为我们做了更多,他甚至让我们根本不需要关心着些“图片”什么时候放入容器,也不需要我们关心如何来维护这些“图片”,我们要做的就是选择“图片”和为图片添加“行为”,但是为了开发的灵活性,我们需要理解这些“图片”如何加载,如何维护等知识。

ASP.NET页面生命周期

         引用MSDN上的一张表:

         一般来说,页要经历下表概述的各个阶段。

阶段

说明

页请求

页请求发生在页生命周期开始之前。用户请求页时,ASP.NET 将确定是否需要分析和编译页(从而开始页的生命周期),或者是否可以在不运行页的情况下发送页的缓存版本以进行响应。

开始

在开始阶段,将设置页属性,如 Request和 Response在此阶段,页还将确定请求是回发请求还是新请求,并设置 IsPostBack 属性。此外,在开始阶段期间,还将设置页的 UICulture 属性。

页初始化

页初始化期间,可以使用页中的控件,并将设置每个控件的 UniqueID 属性。此外,任何主题都将应用于页。如果当前请求是回发请求,则回发数据尚未加载,并且控件属性值尚未还原为视图状态中的值。

加载

加载期间,如果当前请求是回发请求,则将使用从视图状态和控件状态恢复的信息加载控件属性。

验证

在验证期间,将调用所有验证程序控件的 Validate 方法,此方法将设置各个验证程序控件和页的 IsValid 属性。

回发事件处理

如果请求是回发请求,则将调用所有事件处理程序。

呈现

在呈现之前,会针对该页和所有控件保存视图状态。在呈现阶段中,页会针对每个控件调用 Render 方法,它会提供一个文本编写器,用于将控件的输出写入页的 Response 属性的 OutputStream 中。

卸载

完全呈现页并已将页发送至客户端、准备丢弃该页后,将调用卸载。此时,将卸载页属性(如 ResponseRequest)并执行清理。

         可以看出,页面经历了许多个步骤才最终形成我们所看到的页面。然后各个步骤都在做不同的事,我们可以重载掉这些方法,然后添加自己的逻辑

        

Public class BasePage: System.Web.UI.Page

{

         Protected override void OnInit(EventArgs e)

         {

                   //TODO…

}

…..

}

然后在我们的页面中使用我们重载过后的Page,我们先观察aspx页面的头部会发现这么一句:CodeBehind=”…..cs” Inherits=”……cs”,前一个是该页面的后置代码,后一个就是该页面继承至某一个类,然后我们打开后置的代码文件。可以看到该类继承至System.Web.UI.Page,这时怎么修改已经很明了了,只需要将这里的继承改成我们自己的BasePage就可以了

在重载System.Web.UI.Page 的时候会发现每个阶段的On事件处理函数,下面对几个常用的处理函数进行分析,按照执行顺序,如下:

1、OnPreInit:当框架调用该方法时,引发PreInit事件。在该事件中主要是应用App_Themes中的主题,与应用母版页,通常这一步我们不需要做什么

2、OnInit: 在这一步中,框架将初始化该页面所应用到得控件,然后将应用的Themes应用给控件,递归的触发子控件的Init方法。

3、OnInitComplete:这是一个标志事件,他的调用标示这初始化完成,所有子控件均已经初始化完毕,所以Themes都已经应用。

4、OnPreLoad:该事件标志着页面进入加载状态,在该事件中,框架会为自身和所有控件加载视图状态,然后会处理Request实例包含所有回发数据。

5、OnLoad:Load事件是我们通常运用最平凡的事件,也就是Page_Load事件,Page_xxx是所有时间的一种时间链接形式,如Page_Init将调用OnInit方法。这个事件中可以处理回发,由于视图状态,Themes,子控件都已经初始化完毕,所以便于我们添加逻辑而不必担心被其他事件把值给覆盖掉。值得注意的是,任何页面的Load顺序是先自己,再子控件,如:一个aspx页面被调用Load事件,先加载本身,然后再加载如母版页、用户控件、第三方服务器控件等。

6、OnLoadComplete:标志着所有控件的加载完成。下一步则是将加载内容进行呈现。

7、OnPreRender:该事件处理准备呈现的一些工作,如,对设置了DataSource的控件进行DataBind,通常,我们可以在这个事件上动态修改某些控件的值。

8、OnPreRenderComplete:该事件标志着准备呈现完成,数据已经完成绑定。

9:SaveViewState:该事件中,将序列化ViewState,然后再页面中以一个input:hidden的元素保存试图状态。

10:Render:在这个阶段,框架会调用所有控件的Render方法,进行页面呈现。以生产html页。

11:Unload:在页面生命周期结束后,进行卸载。

跳出ASP.NET控件模型

         从以上的分析可以看出,ASP.NET控件模型的编程方式是纯服务器端得编程,我们做的一切工作都是服务器端得开发,就算是写aspx页面,也只是在告诉框架,我需要些什么东西,这些东西我需要他按照什么样的形式来工作,然后框架会按照我们制定的方法进行生成一张全新的html页面递交给客户端(严格来说是生成一个流)。

       是否感觉这样的一个流程很规范,但却有些臃肿,有时,我们仅仅是需要一个input:text,为什么我却要写一个asp:TextBox,还要需要初始化一个TextBox对象,还要序列化、保存ViewState。有时,我数据命名已经准备好了,为什么不能直接生成html代码,还需要ViewState、还要加载,然后呈现。诸多问题让我们感觉,微软视乎给我们提出了一个非常便捷,简易的变成模式,但却引入了很多臃肿的流程。

         其实,我们完全可以跳出控件模型的编程思想。这时,还记得asp的编程方式吗?或则,有试过php吗?再或者,对javascript的工作方式是不是还记忆犹新?对,改变其实很简单,请看以下工程实例。

2011052015233351.png

         这个示例工程包含表现层,业务逻辑,资源访问层和公共资源层,表现层通过ServiceClient工程访问业务逻辑层,公共资源层其中包含模型,和一些Helper方法。

         目前,我们需要讨论的是如何跳出ASP.NET控件模型的编程方式,现在我们需要关心的是PL.Web工程的Default.aspx文件,可以看到这个文件没有后台cs代码。具体页面代码如下:

<%@ Page Language="C#" AutoEventWireup="true" Inherits="PL.Handle.BasePage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head>

    <title></title>

    <script runat="server">

        private List<DemoModel> list;

        private void Page_Load(object sender, EventArgs e)

        {

            HttpMehotd httpmethod = Request.GetHttpMethod();

            //TODO 这里通常是为了准备一些数据,如这里可以调用PL.ServiceClient中的方法,通过BLL获取数据,

            //但为了演示方便这里仅仅是初始化一些简单数据

            list = new List<DemoModel>() { 

                new DemoModel(){Title="标题",Content="内容"},

                new DemoModel(){Title="标题1",Content="内容1"}

            };

            //如果是Post表单,交与post处理函数进行处理

            if (httpmethod == HttpMehotd.Post)

            {

                HttpPostHandle();

            }

        }

        private object HttpPostHandle()

        {

            //TODO

            return null;

        }

    </script>

</head>

<body>

    <form method="post" action="Default.aspx">

    <%if (list != null)

      {

          foreach (var item in list)

          {%> 

            <div><%=item.Title %></div>

            <div><%=item.Content %></div>        

        <%}

      } %>

      <select name="seldemo">

         <%if (list != null)

          {

              foreach (var item in list)

              {%> 

                <option value="<%=item.Title %>"><%=item.Content %></option>       

            <%}

          } %>

      </select>

      <input type="submit" value="提交" />

    </form>

</body>

</html>

         首先我删除了CodeBehind属性,并将Inherits指向了一个BasePage类,该类继承至System.Web.UI.Page。在head标签中添加一个script标签,并设置该标签的runat属性为server标示这是服务器段代码,在该标签中书写处理逻辑。之后在body标签中,去掉了form标签的runat属性,并手动设置了method为post,action为本身,就是说当提交表单时,是提交给自己进行处理。最后在form中按照预定逻辑控制需要生产的html代码。这样一来,虽然任然要走诸多生命周期事件,但是由于页面中不存在任何服务器控件,所以这一步大大被简化,当处理动态数据时我们也仅仅是按照html的预定模式进行控制输出,而不存在处理数据绑定,序列化等繁杂的工作。

         也许您已经发现。这正是MVC的思想,Page工程其实只是一个View,而ServiceClient是Controller,Data.Models工程就是所谓的Model。自然而然,运用这样的变成模型也是有利于单元测试

前台后台分离

         这里所描述的前台后台分离知道是,前台开发人员不需要知道任何后台开发的知识,后台开发人员需要的仅仅是纯html页面,然后就能够进行后台开发。如果是ASP.NET控件模型这一点是很难办到的。

         最后,希望本篇文章能对大家有所帮助,也希望以上编程模型能得到大家的应用,优点处理前后台分离以外,还有缩短处理周期,便于单元测试,便于扩展等诸多优点。

参考文献

《MSDN ASP.NET页生命周期概述》:

http://msdn.microsoft.com/zh-cn/library/ms178472(VS.80).aspx

转载于:https://www.cnblogs.com/GuoPeng/archive/2011/05/20/2052015.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值