ASP.NET页面状态管理——ViewState的使用

ASP.NET ViewState设计目的是为了持久化当前页面中的对象的状态,以便下次在页面回发(Postback)后能够还原页面的状态。那么有两点需要注意:

  1. ViewState只在需要Postback的页面里才需要使用;
  2. 在1前提之下,只有初始状态值被修改了的对象才需要持久化,即才需要使用ViewState。

第1点比较清楚,来谈第2点。以简单的Label控件为例,先来看一下它的Text属性的实现:

public virtual string Text
{
    get
    {
        object obj2 = this.ViewState["Text"];
        if (obj2 != null)
        {
            return (string) obj2;
        }
        return string.Empty;
    }
    set
    {
        if (this.HasControls())
        {
            this.Controls.Clear();
        }
        this.ViewState["Text"] = value;
    }
}

很显然Text属性的后端都是以ViewState为存储介质的,ASP.NET服务器端控件的很多属性都是以类似方式实现的。假设一个页 面default.aspx里只有一个Label控件, <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>,当访问该页面时,Label控件发送到客户端浏览器的代码大概为 <span id="xxx_Label1">Label</span>,同时ViewState中也保存了一份Text属性的值,形式大概为<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTgwMzg2ODMxMQ9kFgJmD2QWAgIDD2QWAg......

到目前位 置,ViewState并没有发挥作用(这里谈论的都是在ViewState Enable的情况下),额外的保存了Text属性的值在这里是多余的。假设该页面还有一个Button控件,点击该按钮页面回发,那么在次过程中 ViewState就发挥作用了么?分析一下该页面回发过程中Label控件生命周期的某些过程。首先,回发后,Label控件依然要经历初始化阶段 (Init),这个阶段要创建一个Label控件的实例,同时设置其Text属性的,因为Text属性后端是以ViewState为存储介质的,所以就相当于向ViewState里添加了一个值,接下来,因为是回发过程,所以控件还要LoadViewState,即加载前次访问该控件的状态值,下面是Label控件的实现:

protected override void LoadViewState(object savedState)
{
    if (savedState != null)
    {
        base.LoadViewState(savedState);
        string text = (string) this.ViewState["Text"];
        if (text != null)
        {
            this.Text = text;
        }
    }
}

因为在前一访问过程中ViewState中所保存的Label的Text属性的状态值 就是Label的初始值,所以导致了这里的LoadViewSate过程是多余的了,而且Init和LoadViewState两个过程对Text属性都 赋了相同的值。由此可见,即使在页面回发中,如果不需要对属性的初始值进行修改,那么持久化属性的值(即使用ViewState)也是没有意义的。而且会 带来多余的资源浪费,如两次对Text属性的赋值,以及增加了ViewSate的体积所带来的多余的网络传输。

那么,什么情况下使用ViewSate是值得的呢?我们先来把前面例子中两次访问的过程理一下:

  1. 第一次访问页面,Label控件初始化,设置Text属性的值,即向ViewState中添加了一个条目;
  2. 页面发送前(Render前),控件SaveViewState,即ViewSate中的值序列化,保存到一个隐藏域中;
  3. 页面发送,Label控件发送为相应的HTML标签,读取Text属性设置HTML标签的对象属性值,同时发送隐藏域及其值。对于Labe的Text属性来讲,相当于一份ViewState中的值发送了两份客户端拷贝;
  4. 第二次回发访问,Label控件初始化,设置Text属性的值,即向ViewState中添加了一个条目;
  5. 由于是回发访问,需经历LoadViewState过程,本例中即读取ViewState中Text属性在上一次访问中的状态值,而这个值实际上等于过程1中设置的值,读取的值再次设置Text属性,
  6. 第二次发送,重复过程2,3.

从过程1控件初始化,到过程6,第二次发送前SaveViewState,在这两个过程中间,如果不需改变Text属性的初始值,那么实际上就不需要使用ViewState。假设我们在过程1、2中间改变Text属性值,如在Page_Load中如此:

protected void Page_Loadt(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Label1.Text = "Change Label′s value";
    }
}

 那么,尽管在回发时不能执行Label1.Text = "Change Label´s value";语句,但由于ViewState的作用,第一次访问设置的值,在第二次回发访问后仍然会存在,即Label的Text属性值为 ”Change Label´s value“,而不是其初始值“Label”。这种情况下才是ViewState的用武之地。注意!IsPostBack的使用,否则你只是每次访问都进 行赋值而已,并没有利用ViewState的好处。

由此,可以得出,在满足前面所述的两个条件时才应该使用ViewState。那么在现实应用中同时满足以上两个条件的情况下多么,也就是说我们需要使用ViewSate的时候多么?

很显然,满足这两个条件最大宗的情况就是数据绑定。而我认为ViewState的设计目的主要就是为了将必要的信息持久化在页面中,避免在 两次访问中(确切的说不只两次,而是所有的回发访问中)都要进行数据绑定(而每次数据绑定往往意味着一次次的数据库访问)。例如用GridView绑定 DataSource控件展现一个类表数据,在ViewSate Enable的情况下,页面第一次加载时进行数据绑定,在随后的回发访问中,如果仍是访问当前数据视图,即没有进行分页、排序操作 等,DataSource不会再进行数据绑定,因为所有的信息都可以从ViewSate中获取,不需要再次访问数据库再次绑定数据控件了。而如果你将 ViewState Disable掉,那么每次访问则都需要进行数据绑定了(可以通过SqlProfiler来捕捉SqlDataSource在两种情况下对数据库的访问情 况)。这个场景可能最能说明ViewSate的设计初衷了。

然而在实际的应用中,上面的这种场景多么?在数据列表页面,往往没有除了分页排序等之外的回发操作(你放Grid的页面里有回发的按钮 么?),而分页,排序操作所引起的回发显然是需要数据再绑定的。如果是这种场景,那么你就应该把这个页面或者把这个Grid的EnableView属性设 为false了。这里讲点题外话,有人会说如果设成false,那Grid的分页信息、排序信息怎么传递给后续的回发访问呢?其实在ASP.NET 2.0中控件的状态管理被分为了两部分view state和control state。两者的区别是什么呢,那ASP.NET 1.x中的DataGrid控件来说,DataGrid的所有状态信息都保存在view state当中,但是这些信息所符合的view state应用场景是矛盾的,比如你的页面没有回发操作,你不必把所有数据缓存到view state里,这时你会把datagrid的enableviewstate属性设为false,但当你这么做后,datagrid的另一些功能如翻页、 排序,就没法使用了,因为翻页排序的状态信息也是保存在view state中的,如pageindex、sort asc/desc等。就类似于这种问题,ASP.NET 2.0中又引入了control state,control state的存储方式与view state相同,不同的地方在于它不会被disable掉。这样control state用来存储那些控件的功能性的,必需的信息。比如即使GridView的view state被禁止了,它的分页,排序等信息还是仍然正常工作的。

ASP.NET的一些设计,如整个页面一个form元素,以及本文谈到的view state的使用等,只是在宏观上,概率统计上能达到节约成本,提高效率的目的。但是具体到一个Web程序, 一个应用场景,一个页面,甚至是一个控件,如果你知到它们背后的东西,你就会更好更正确的去实现它或使用它。

Read More →

IE6--让我说你什么好!编码!还是编码!

一鼓作气把博客的小BUG改了一下,搞了两个小时的CSS,在IE6中一直显示不正常,唉,真是不太爽~~

后来才发现是编码的问题,网页用的是UTF8编码,这是我的一惯作风,但是这个CSS文件不知是什么原因居然是GB2312的,唉,结果导致解析不正常了,这个在用外部引用javascript文件的时候,如果编码不一致,也可能出问题。

养成好习惯,统一编码,努力做好~~

Read More →

IE7无法卸载-解决方案

下载Internet Explorer 7 Beta 2 Uninstall Toolkit工具

 我们可以到这两处下载:

http://download.microsoft.com/do ... 6-enu-UNINSTALL.exe

http://download.pchome.net/system/uninstall/33223.html

Read More →

在水晶报表中如何显示一个变量的值

要显示水晶报表的值必须添加参数字段,具体方法是:字段资源管理器-->参数字段-->新建,名称我们填写fromTime其他的保持默认,此时如果不在程序中给这个变量赋值的话,调试运行程序的时候,会自动提示输入。

假如我们的报表文件是:CrystalReportList.rpt,下面的代码在程序中给参数字段赋值:
CrystalReportList gxyCR = new CrystalReportList();
gxyCR.SetDataSource(dt);
gxyCR.SetParameterValue("fromTime", WindowsApplication.Form1.fromTime);
gxyCR.SetParameterValue("toTime", WindowsApplication.Form1.toTime);

备注,我做的报表是显示介于fromTime和toTime这两个时间之间的记录打印出来,所以设了两个参数,发现给参数赋值的代码必须出现在的gxyCR.SetDataSource(dt);之后,这个还没找到答案

Read More →

Microsoft .NET Framework 2.0 Service Pack 2

.NET Framework 2.0 Service Pack 2是专为解决客户在.NET Framework 2.0发布后报告的问题而提供的累积更新。此外,此发行版为.NET Framework 3.5 Service Pack 1提供了性能改进和必备功能支持。请在系统需求一节中查看此部署程序包支持的操作系统。Microsoft Vista 的相应更新和Microsoft Windows 2008的相应更新可通过完整的.NET Framework 3.5 service pack 1 部署。

Microsoft .NET Framework 2.0 官方下载:
http://www.microsoft.com/downloads/details.aspx?familyid=0856EACB-4362...
Microsoft .NET Framework 2.0 Service Pack 1 官方下载:
http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&Fami...
Microsoft .NET Framework 2.0 Service Pack 2 官方下载:
http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&Fami...

Read More →

javascript 判断是否为数字

isNaN 函数
isNaN(expression:Object) : Boolean

计算参数,如果值为 NaN(非数字),则返回 true。此函数可用于检查一个数学表达式是否成功地计算为一个数字。

可用性:Flash Player 5;ActionScript 1.0

参数
expression:Object - 要计算的布尔值、变量或其它表达式。

返回
Boolean - 一个布尔值。

Read More →

很精典,很雷人

一员工向老板请一天假,老板推心置腹地说:"你想请一天假,你在向公司要求什么? 一年里有365天,52个星期。你已经每星期休息2天,共104天,还剩下261天工作;你每天有16小时不在工作,去掉174天,还剩下87天;每天你至少30分钟时间上网,加起来每年23天,剩下64天;每天午饭时间用掉1小时,又用掉46天,还有18天; 通常你每年请2天病假,这样你的工作时间只有16天;每年有5个节假日公司休息不上班,你只干11天。 每年公司还慷慨地给你10天假期,算下来你就工作1天,而你他妈的还要请这一天假

----该职员当场无语猝死

Read More →

PHP 文件上传

创建一个文件上传表单

允许用户从表单上传文件是非常有用的。

请看下面这个供上传文件的 HTML 表单:

<html>
<body>

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

请留意如下有关此表单的信息:

<form> 标签的 enctype 属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,请使用 "multipart/form-data"。

<input> 标签的 type="file" 属性规定了应该把输入作为文件来处理。举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮。

注释:允许用户上传文件是一个巨大的安全风险。请仅仅允许可信的用户执行文件上传操作。

Read More →

Activex 部件不能创建对象故障解决

今天下了一个phpmaker玩玩,发现不能生成PHP代码,出现了Activex 部件不能创建对象的对话框,保存时也出现了类似的情况~~~

regsvr32 "C:\windows\system32\scrrun.dll",搞定。。。

Read More →

二进制算术操作笔记-php

最近在想一个加密码算法,参考了DISCUZ的加密算法,位操作显然是主要的运算。

自己写的算法还有一些BUG,先不发了,总结一下PHP的一个心得,我所遇到的问题是移位操作,如果是´j´ >> 2,这个在PHP中结果是0,这个结果有点出乎意料,不过如果:´j´ & ´m´,结果是h,不知道问题在哪里。。。

GOOGLE了一下,找下如下的文字:

二进制算术操作的隐式类型转换规则:整型与浮点型时,整型转换为浮点型;整型与字符串时,字符串转换为数字,如果转换后的值是浮点型,则将整型转换为浮点型;浮点型和字符串,字符串转换为浮点型。
字符串连接操作符“.”在连接字符串之前将两个操作数都转换为字符串。
字符串在转换为数字的时候,若在字符串开头没有发现数字,字符串的数值就是0。如果字符串包括一个句点“.”或“e,E”,对该字符串求值则生成一个浮点数。

估计问题就在这了,整型与字符串时,字符串转换为数字,这的样的话,´j´转化成数字是不存在的,估计就成0了,不过问题还有:若在字符串开头没有发现数字,字符串的数值就是0,什么叫开头没有发现数字?

Read More →
在线学习答案查询入口
微信扫一扫
微信扫码联系