深入了解ViewState

 

Web 是没有状态的,ASP.NET 页面也没有状态,它们在到服务器的每个往返过程中被实例化、执行、呈现和处理。作为 Web 开发人员,您可以使用众所周知的技术(如以会话状态将状态存储在服务器上,或将页面回传到自身)来添加状态

ViewState是一种机制,ASP.NET 使用这种机制来跟踪服务器控件状态值,否则这些值将不作为 HTTP 窗体的一部分而回传。也就是说在页面刷新或者回传的时候控件的值将被清空,我们在aspx.cs中也经常用ViewState来存储值,作为一种存储状态,取代会话状态(session),举个例子

1、一般的服务器控件

<asp:Label ID="Label1" runat="server" Text="这是Label1的值"></asp:Label>

<asp:Button ID="Button1" runat="server" Text="Button" />

如果点击Button1,则触发按钮事件

protected void Button1_Click(object sender, EventArgs e)

    {

        Label1.Text = "改变Label1的值";

    }

很显然Label1的值会显示为“改变Label1的值”,对ViewState有了解的人应该知道,这是因为ASP.NET用这种机制把Label1保存至__VIEWSTATE这个隐藏域中,然后回传时直接从此隐藏域中取值,赋值给Label1,减轻服务器负担,在页面查看源文件可以看到这个,这个是base64编码的字符串,并不是加密,更复杂的说且是在方法Page.SavePageStateToPersistenceMedium输出前保存、并由Page.LoadPageStateFromPersistenceMedium加载,对于这两个方法大家可以去研究

  <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNjkxODQwNzM1ZGREm/D7KtJXowDFHnrxVg6pUDM3rQ==" />

如果是纯HTML控件,每次回传必然会回到控件的初始值

 

但是我们可以禁用ViewState机制,只要在控件或者page或者在web.config上配置,比如

<asp:Label ID="Label1" runat="server" Text="这是Label1" EnableViewState="False"></asp:Label>

则点击上面按钮时,Label1的值会显示为“这是Label1”,而并不是改变Label1的值,这是因为ViewState 负责穿越回传期保持它的值。但又因为 ViewState 是 禁止 的, 所以 Label 丢失了ViewState为其保存的值,于是变回到初始值

 

2、特殊的服务器控件

我们再举一个例子

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>//服务器控件

<input type="text" id="TextBox2"  runat="server"  />//HTML控件,但是加了服务器标识

<input type="text" id="TextBox3"  />//HTML控件

<asp:Button ID="Button1" runat="server" Text="Button" />

 

点击按钮,

 

发现第一个服务器控件,第二个加了服务器标识的HTML控件,页面回传时值没有变化,而第三个纯HTML控件值被清空,即回到初始值,这种情况使我们早就料到的,于是我们继续尝试着,对服务器控件试用EnableViewState="False",再来看结果

 

点击按钮,

 

这个结果真是让我们失望,很明显我已经禁用ViewState,理应该是三个控件值都为空,即都回到初始值,考察资料得到

ViewState 是不负责存储诸如 TextBox等这些继承自 IPostBackDataHandler 接口的控件的值的更改的。

简单的说继承自 IPostBackDataHandler 接口的控件的值由控件自身控制保存,而与EnableViewState=false没有关系,前台页面__VIEWSTATE的值是控件自身控制写入_VIEWSTATE的,怎么写入的要看IPostBackDataHandler 接口的实现方式【先反序列化ViewState,然后 LoadPostData 事件被触发,然后把反序列化后的值写入控件,具体见http://msdn.microsoft.com/zh-cn/library/system.web.ui.ipostbackdatahandler.aspx,说实话我也不知道我理解的对不对。求大神指教】

大概如下图

 

 

在微软的帮助文档中得知(http://support.microsoft.com/?id=316813)

 

也就是说通常情况下类似TextBox发送到服务器的属性由 IPostBackDataHandler 界面来处理,不管VIEWSTATE有没有禁止,它都会在回传时往里面填值,当然这个值是来自HTTP 提交头里

 

3、我们经常试用的Viewstate

我经常在aspx.cs中试用Viewstate来存储数据状态,比如

Viewstate[“name”]=”殷海超”;,然后程序会把这个Viewstate保存为键-值对形式,这是会有一个序列化和反序列化的过程(序列化就是将对象的状态信息转换为可以存储或传输形式的过程。其实就是将对象持久化,比如说把对象保存为二进制或者是XML的方式。可以将对象序列到流、磁盘、内存和网络等等。相反,反序列化则是将存储或传输形式转换为对象的过程。),Viewstate[“name”]=”殷海超”这是序列化,因为其实这里是序列化为字符串放置至HTML页面中(中间过程何其复杂。还未理解);string name= Viewstate[“name”];这是反序列化

 

4ViewState为控件赋值的步骤

 

protected void Page_Init(object sender, EventArgs e)

{

        TextBox1.Text = "bb";

}

protected void Page_Load(object sender, EventArgs e)

{

        TextBox1.Text = "aa";

}

未操作之前,我们往第一个控件中输入cc

 

我们点击按钮后:显示下图

 

先执行Page_Init()事件,TextBox1.Text先会是bb,然后执行称为 LoadViewState 的事件,在这里 Page 类从隐藏的域 __VIEWSTATE 中为诸如 ViewState 属性为 enabled 的 Label 控件装载值。然后 LoadPostBackData 事件被触发,在这里 Page 类从 HTTP 提交头(POST headers)中装载继承自 IPostBackDataHandler 接口的控件的值,即这时TextBox1.Text是cc,然后会执行Page_Load,这时TextBox1.Text是aa

 

 

posted @ 2012-05-31 16:24  蹦极的馒头  阅读(3242)  评论(5编辑  收藏  举报