没有合适的资源?快使用搜索试试~ 我知道了~
viewstate详解,详细阐述了viewstate的用法及其作用。
资源推荐
资源详情
资源评论
【转】ASP.NET ViewState 详解
作者:Infinities Loop
概述
ViewState 是一个被误解很深的动物了。我希望通过此文章来澄清人们对
ViewState 的一些错误认识。为了达到这个目的,我决定从头到尾详细的描述
一下整个 ViewState 的工作机制,其中我会同时用一些例子说明我文章中的观
点,结论。比如我会用静态控件(declared controls)和动态控件(dynamic
controls)两个方面来说明同一个问题。
现在有关 ViewState 的文章可谓多如牛毛,你可能会说再写有关 ViewState 的
文章无异于炒剩饭(我这篇文章便是:D)。但是我却不这么认为,如果把
ViewState 看成一匹野马的话,那么这匹野马并没有死去,它还活跃的很,说
不定这个时候它正在你的客厅里撒野呢。所以我们有必要再次去把它击倒。不
过你也不需要担心,从这篇文章你可以发现其实这匹马也没有那么坏。
我的意思并不是否然目前还没有好好说明 ViewState 的文章,只是我总觉得好
像这些文章都缺少一些东西,而这些缺少的东西往往就会导致人们对
ViewState 的困惑。比如:理解 ViewState 是怎样跟踪那些已经出现变化的数
据(dirty data)就非常重要,但是很多文章却没有过多的涉及,或者即便涉及了
可能其中却包含了错误的信息。比如这篇文章(W3Schools)中就说页面回传的
值也是保存在 ViewState 中的,但是这个观点是错误的。不信是吗?那么你在
一个页面上放置一个 TextBox 控件和一个 Button 控件,然后你在“属性”中将
TextBox 的 EnableViewState 设置为 False,然后通过点击 Button 回传页面,
你会发现 TextBox 还是仍旧会保留你输入的值,而不会如你想象的由于
TextBox 的 ViewState 被禁用了而导致 TextBox 的值在页面回传的过程中消
失了。还有一些文章(#1 Google Search Result , ASP.NET Documentation
on MSDN )描述了服务器控件如何在页面的回传中保持自身状态。这些文档虽
然没有全错,但是有些描述还是存在一些不准确的地方,如:
"If a control uses ViewState for property data instead of a private field, that
property automatically will be persisted across round trips to the client."
(如果一个控件用
ViewState
而不是用类的私有字段
(private field)
来存储数据,那么这些控件
属性的值将会自动在页面回传之间保持状态??
[
这句话的意思有待确定
])
上面这句话似乎在暗示任何东西只要是保存在 ViewState 状态包(StateBag)中,
那么就会在服务器和客户端页面回传的过程中被传递。(That seems to imply
that anything you shove into the ViewState StateBag will be round-
tripped in the client's browser. NOT TRUE!)不对!所以说对于 ViewState
控件的困惑还是存在的。而且在 Internet 上我目前还没有找到一篇 100%准确
完整的描述 ViewState 工作的文章。我目前找到的最好文章是这一篇(this one
by Scott Mitchell)。这篇文章是值得一读的。然而这篇文章还是有些美中不足,
它没有描述在控件初始化和 ViewState 跟踪的时候父控件和子控件之间的关系。
而恰恰就是这一点就会导致对 ViewState 大量的误解,至少我是有过这种经历
的。
根据上面的情况,这篇文章从最开始先会对 ViewState 实现的功能进行一个完
全描述。然后对 ViewState 的实现进行一个详细的阐述,在这个过程中我会同
时举一些相对应的例子,通常我会先举一个开发人员经常会犯的错误的例子,
然后再举一个例子来表示如何修正错误。在这里我需要实现声明一下的是,虽
然在 ASP.NET 2.0 中 ViewState 的实现机制有稍许变动,但是在写这篇文章的
时候我依然是以 ASP.NET 1.x 的版本为前提进行的。比如说在 ASP.NET 2.0
的新增了一个新类型的 ViewState -- ControlState, 但是实际上 ControlState
和 ViewState 并不大变,所以我们这里可以忽略它。
首先让我们看看为什么深入了解 ViewState 是如此重要。
对 ViewState 的误解可能导致...
1. 导致一些敏感信息被泄漏;
2. 针对 ViewState 的攻击(aka the Jedi Mind Trick,aka 是又称作,又叫
做的意思。Jedi Mind Trick, 看过星球大战的人对于 Jedi 一定不陌生,
Jedi 就是绝地武士。Jedi Mind Trick 是绝地武士的一个招式,可以用
于控制对方的思维。有关这个的具体知识可以参见:http://gollum.easycp.de/
gollum/gollum.php?a=core&l=en&wl=en&q= 这里作者估计是表达了通过
ViewState 的攻击来达到控制对方的目的。比如一个等离子电视的价格
被修改为了 1 美元一台)
3. 很差的性能,在某些极端的情况下可能根本就没有性能。
4. 并发性差 -- 想象一下如果每次回传的数据都有 50kB,那么你的服务器
能承受多少并发的访问量呢?
5. 糟糕的全局设计;
6. 以上结果一定会让你抓狂的(头痛,反胃,头昏眼花,皱眉头...)。
如果你正在开发基于 ASP.NET 平台的网络应用程序,并且你无视 ViewState
存在的话,那么以下的情况可能会发生在你的身上。
The ViewState form eld.
看看你页面的
HTML
源代码吧,密密麻麻很恐怖吧。
ViewState will add your web app's
distinctiveness to it's own.
Performance is futile. 沉重的星际垃圾
像如上的例子我还可以举出很多,但是我想这两个例子已经具有代表性了。好
了,现在让我们从最开始认识 ViewState 吧。
ViewState 可以用来做什么?
这里列举的每一项都是 ViewState 需要完成的主要工作,我们将根据这
些工作来学习 ViewState 是如何实现这些功能。
1. 以名值对的方式来存控件的值,和 Hashtable 的结构类似;
2. 跟踪那些 ViewState 中出现改变的值,以便对这些脏数据(dirty)进行进
一步的处理;
3. 通过序列化将 ViewState 中的值保存在页面的隐藏域(Hidden Field)中
(这是默认的持久化方式),并通过反序列化得到对应的 ViewState 对象
以便进行相应的操作;
4. 在页面回传的过程中自动的存储 ViewState 中的跟踪的值。
下面列举的是 ViewState 不能用来做什么的列表,这个其实比了解 ViewState
是用来做什么的还重要。
什么是 ViewState 不能做的?
1. 自动保存一个类中变量的状态,无论是 private, protected 还是 public
的变量;
2. 可以在页面回传的过程中记住所有状态值;
3. 只要有了 ViewState 那么每次页面请求时重新构造的数据的操作是不必
要的了;
4. ViewState is not responsible for the population of values that are
posted such as by TextBox controls (although it does play an
important role) ViewState 并不存储那些通过 Post 名值对回传的数据
值(如 TextBox 的 TextBox.Text);
5. 想让 ViewState 替你泡一杯咖啡,做梦吧:P。
虽然 ViewState 作为一个整体出现在.NET Framework 框架中有它的唯一目的,
那就是在页面回传的过程中保存状态值,使原本没有“记忆”的 Http 协议变得有
“记忆”起来。但是上面列举的 ViewState 的四个主要功能之间却没有太多的关
联。所以从逻辑上我们可以将其划分开来,各个击破。
哈哈,这样大小的 ViewState 是不是更加好下口了?
1. ViewState 就是用来存储数据的
如果你曾经使用过 HashTable 的话,那么你应该明白我的意思了。这里并没有
什么高深的理论。ViewState 通过 String 类型的数据作为索引(注意在
ViewState 中不允许通过整形下表的方式对其中的项进行访问,如:
ViewState.Item(0) 的形式是不允许的。)ViewState 对应项中的值可以存储任
何类型的值,实施上任何类型的值存储到 ViewState 中都会被装箱为 Object
类型。以下是几个对 ViewState 进行赋值的几个例子。
ViewState["Key1"] = 123.45M; // store a decimal value
ViewState["Key2"] = "abc"; // store a string
ViewState["Key3"] = DateTime.Now; // store a DateTime
实际上 ViewState 仅仅就是一个定义在 System.Web.UI.Control 类中的一个保
护类型(Protected)
的属性名称。由于所有服务器端的控件,用户自定义控件还有页面(Page)类都
是继承自 System.Web.UI.Control 类,
所以这些控件都具有这些属性。ViewState 的真正类型实际应该是
System.Web.UI.StateBag 类。
严格的说,虽然 StateBag 类虽然定义在 System.Web 的命名空间下,实际上
StateBag 类
和 ASP.NET 并没有严格上的依存关系,它也完全可以放在
System.Collections 命名空间下。
事实上许多服务器端控件大多数属性值都是利用 ViewState 来进行数据存储。
你可能认为
TextBox.Text 属性是按如下形式存储的:
public string Text
{
get { return _text; }
set { _text = value; }
}
但是你必须注意,上面的形式(通过类的私有字段)并不是大多数 ASP.NET 服务
器控件存储其属性值得方式。这些控件的属性值大多是通过 ViewState 来进行
存储的。通过 Reflector 查看 TextBox.Text 属性的源代码你可以看到类似如下
的代码:
public string Text
{
get { return (string)ViewState["Text"]; }
set { ViewState["Text"] = value; }
}
为了表示这个观点的重要性,我这里再重申一遍“大多数 ASP.NET 服务器控件
存储其属性值得方式是通过 ViewState 的方式存储的,而不是我们通常想象的
那样通过类的私有字段来存储。”即便是用于设定服务器控件样式的 Style 类中
的大多数属性值也是通过 ViewState 来进行存储的。所以在设计自定义的组件
时,对于那些需要存储的组件属性值也最好遵循这个方式。这里我还需要着重
讲一个问题,在以 ViewState 为存储方式的情况下,如果实现属性的默认值
(default value),我们可能会认为属性值是这样实现的:
public class MyClass
{
private string _text = "Default Value!";
public string Text
{
get { return _text; }
set { _text = value; }
}
}
这样如果在对 Text 的属性没有设置的时候,直接取 Text 属性,那么我们可以
得到默认值"Default Value!"。那么如果我们使用 ViewState 来存储的时候如
何实现默认值呢?如下所示:
public string Text
{
get
{
剩余21页未读,继续阅读
资源评论
孑然一身
- 粉丝: 1
- 资源: 18
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功