ViewState是ASP.NET的一个独创设计。它为用户在进行Web开发时带来了极大的便利,特别是对于一个WEB开发新手来说,它完全可以不用自己去维护WEB控件的状态,在进行事件驱动开发时,用户只管通过控件ID来获取当前控件的值,而其它的细节ASP.NET都是对用户透明的,所以非常易于入门。而它所带的负面影响也是明显,有时候也是而严重的,最严重的就如上的那篇回发事件执行很慢,甚至时常出现“Validation of viewstate MAC failed”你也不会感到意外。

     那么我们该如何来控制和使用ViewState呢?我想最好还是禁用它,但是也不绝对是这样的。你可以根据你的应用来决定是否禁用ViewState,那么决定因素有哪些呢?

     1)你的生产环境,也就是说你是在哪里使用的。如果你的是在局域网内部,或是光纤到桌面(也不用光纤,速度有保证就行,这里只是一个比喻)。那么你可以放心使用ViewState。

     2)你对Web开发的理解程度。这是主观因素,如果你对禁用ViewState有足够的控制能力,那么你可以放心的在web.config全局禁用ViewState。

     3)如果你主观上能够接受ViewState,你希望能充分利用它给我们带来的便利。并且你可以很好的控制ViewState,不让它成为你的性能瓶颈。

     4)你的应用场合,比如你如果是网站前台的话,那请尽量禁用ViewState。(当然也最好不要使用PostBack)

     可能还有其它的原因来决定你是否使用ViewState。这里我们还是希望能够来总结一下ViewState带给我方便的同时,它都带了什么副产品给我们了:

     1)最直观的就是页面体积。使用了ViewState,它会维护所有的控件的状态,在进行PostBack的时候,会适时的进行控件状态的还原。这是什么概念呢?就是控件的值(例如DropdownList里面的所有选项)除了通过HTML的方式显示给用户外,它同时在ViewState中还有一个备份,这个备份会以一个隐含变量的方式存在服务器发送的HTML代码中,同时在PostBack时会把这些ViewState再传回给服务器端。无形中增加了一倍以上的页面体积。

     2)增加了体积了,自然就增加了网络传输。当然页面的反应速度就下降了。

     3)在服务器端增加了一些额外的处理时间。ViewState增加了体积,那么对这些ViewState值的序列化和反序列化的发的时间也是不可小视的。另外,在还原控件状态时,需要对控件进行的遍历和赋值,这个时间也应该算是一个比较大的开销。

     禁用ViewState,解决了一些问题。但是做为WebForm生命周期的一部分,那个ViewState处理函数还是需要被调用的,只是它们在判断EnableViewState==false以后,所做的事情就比较少了,也就节省时间了。如果你仔细查看一下禁用ViewState的页面,你还会发现有隐含变量__VIEWSTATE。如果你想让这个隐含变量也消失,那么你可以重写Page类的PageStatePersister,来达到这个目的。但是据我的经验,这样做以后好像会有一些其它影响,所以这里建议你尽量不要这样做(其实也没必要这么做)。

     那么禁用了ViewState,是不是说我们就无法利用ViewState给我带来方便了?绝对不是这样的,正因为我们禁用了ViewState,那么我们就可以开始“滥用”ViewState了。因为有些情况下,我们需要在相同页面的不同的控件中使用一些相同的值。比如,你在查询完数据后,总页数也要在相同页面中的一些在其它控件里使用。这时因为不同控件不在同一个类中,无法使用变量传递,如果你放在缓存和Session中,那么冲突和过期时间就不是你所控制的了。这时我们就可以把它给存放在ViewState,因为ViewState的作用域仅限本页本次请求,页面输出后就随着页面实例而回收了。而因为我们禁用了ViewState了,这时我们在ViewState存的值并不会被序列化到客户端去。这样的“滥用”反而却会给我们的开发带来非常大的方便和灵活。


ViewState是ASP.NET中用来保存WEB控件回传时状态值一种机制.在WEB窗体(FORM)的设置为runat="server",这个窗体(FORM)会被附加一个隐藏的属性_VIEWSTATE._VIEWSTATE中存放了所有控件在ViewState中的状态值.

   ViewState是类Control中的一个域,其他所有控件通过继承Control来获得了ViewState功能.它的类型是system.Web.UI.StateBag,一个名称/值的对象集合.

   当请求某个页面时,ASP.NET把所有控件的状态序列化成一个字符串,然后做为窗体的隐藏属性送到客户端.当客户端把页面回传时,ASP.NET分析回传的窗体属性,并赋给控件对应的值.当然这些全部是由ASP.NET负责的.

   定义ViewState属性

   public int PageCount

   {

   get { return (int)ViewState["PageCount"]; }

   set { ViewState["PageCount"] = value; }

   }

   使用ViewState的条件

   如果要使用 ViewState,则在 ASPX 页面中必须有一个服务器端窗体标记 (<form runat=server>).窗体字段是必需的,这样包含 ViewState 信息的隐藏字段才能回传给服务器.而且,该窗体还必须是服务器端的窗体,这样在服务器上执行该页面时,ASP.NET 页面框架才能添加隐藏的字段.

   Page 的 EnableViewState 属性值为 true.

   控件的 EnableViewState 属性值为 true.

   提醒:

   1. 当存在页面回传时,不需要维持控件的值就要把 ViewState 禁止.

   2. ViewState的索引是大小写敏感的.

   3. ViewState不是跨页面的.

   4. 为了能包存在 ViewState 中,对象必须是可流化或者定义了 TypeConverter.

   5. 控件 TextBox 的 TextMode 属性设置为 Password时,它的状态将不会被保存在 ViewState 中,这应该是出于安全性的考虑.

   6. 在页面没有回传 或 重定向 或 在回传中转到(transfer)其他页面时不要使用 ViewState.

   7. 在动态建立控件时要小心它的 ViewState.

   8. 当禁止一个程序的 ViewState 时,这个程序的所有页面的 ViewState 也被禁止了.

   9. 只有当页面回传自身时ViewState 才是持续的.

   设置ViewState

   ViewState可以在控件,页,程序,全局配置中设置.缺省情况下 EnableViewState 为 true .如果要禁止所有页面 ViewState 功能,可以在程序配置中把 EnableViewState 设为 false .

http协议是无状态的连接。
那么,对于asp.net页面,如果点击一个button,激发postback产生另一个请求。
那么在处理第二个请求的时候如何知道以前的控件的状态(像textbox的值)呢?

这就用到了ViewState.它是用来维持控件对象的状态的。

如果想详细了解,最好读一下msdn的文章

Understanding ASP.NET View State


基本上所有web控件都含有viewstate,viewstate的作用在于(viewstate为true时)刷新页面时,能够让页面上的数据仍能够保留下来,而不至于例如当你提交完数据后,而返回的页面却是空白的,显得那么的不和谐...
还有viewstate是基于客户端的,可以装载可序列化的对象,用法很简单


自己去测试下

页面上放一个DropDownList,添加几项内容,再放一个Button。选中DropDownList某项后点击按钮回发,
DropDownList能保持选中项状态

然后禁用DropDownList的ViewState,再点按钮看下        


页面回发时,保存页面的状态值!        


viewstate属于状态管理中的概念,可以存储数据状态,这样在刷新页面时就不容易丢失数据,当存储的数据比较大时会影响性能.viewstate可以从页面级,控件级或者应用程序级进行禁用    


ViewState在客户端的保存形式,保存在一个ID为__VIEWSTATE的Hidden中,它的Value是使用Base64编码后的字符串。这个字符串实际上是一个对象序列化之后的结果。这个对象保存了整个页面的控件树的ViewState。可以使用一些工具将这个字符串进行解码查看其内容,比如ViewStateDecoder,ViewStateAnalyzer。
Page对客户端请求进行处理,在处理的过程中先是将客户端提交的_VIEWSTATE反序列化为对象,调用Control的相关方法给所有的控件装载数据,这些数据是上次请求结束后控件的状态数据。在请求结束之前调用Control的相关方法得到所有控件的被修改过的状态数据,之后Page将其进行序列化,并返回给客户端。在Control中又具体调用StateBag类的方法完成状态数据的加载和保存。


通过调用System.Web.UI.Control.TrackViewState()来跟踪ViewState的变化。



viewstate,让你开发网页就像开发桌面应用程序一样
但是我认为它会对你理解B/S造成困难        


简单例子一个,TextBox 的 change事件

服务器端所有的事件都是通过提交表单来实现的

在服务器端将上一次的值和最新值做对比,来触发服务器端的事件,

那么上一次的值存在哪里? 存在ViewState里面,,那么ViewState存在哪里? 它是用来描术页面的历史状态

等信息,需要持久化下来,所以ViewState存在页面上,当然你重写某些方法,也可以存在数据库等地方,    


viewstate形象点说就是客服端和服务器端间数据传递的一个袋子,用的时候取出来,用完就放进去!
这样的原因在于服务器端不保存用户数据,每一次刷新页面客服端都要把信息再传回服务器端。还有就是viewstate中的数据是保存在客服端的。        


1、因为http协议是无状态连接,
2、服务端所有的事件都是通过表单提交的
3、viewstate用来存放页面刷新之前的表单值
4、放在后来使用。