视图状态管理是一种简单且方便的技术。通过视图状态管理,控件开发者可以在一个原本无状态的环境下模拟有状态的且看起来是持续执行的运行效果。其具体过程为:每当用户请求某个.aspx页面时,.NET框架首先把相关控件的状态序列化成一个字符串,然后将其作为名为__VIEWSTATE的隐藏域的Value值发送到客户端。如果页面是第一次被请求,那么服务器控件也将是被第一次执行,名为__VIEWSTATE的隐藏域中只包含控件的默认信息,通常为空或者null。在随后的回送事件中,ViewState中就保存了服务器控件在签名回送中可用的属性状态。这样服务器控件就可以监视在当前被处理的回送事件发生之前的状态了。这些过程是由.NET框架负责的,对用户来说,执行.aspx页面就有了持续执行的效果。
最常见的视图状态管理的方法是应用服务器控件的ViewState属性。ViewState是Syetem.Web.UI.StateBag类型,即一个键/值对的字典,服务器控件的属性值可以存储在ViewState中。
public String Text
{
get
{
return (String)ViewState["Text"];
}
set
{
ViewState["Text"] = value;
}
}
通过set访问器,将属性Text的值写入ViewState["Text"]对象中;通过get访问器,从对象ViewState["Text"]中获取属性值。这就是视图状态处理最简单的方法。在这个过程中的TrackViewState、SaveViewState、LoadViewState等视图状态管理过程都是由.NET框架自动完成的。
默认情况下,ViewState只能保存少数数据类型,它们是String、Int、Bool、Array、ArrayList、HashTable等。如果属性存储的是其他数据类型,则必须编写子定义的视图状态管理程序。
另外,使用ViewState时,对象必须先序列化,然后再通过回传进行反序列化。因此,做为一个优秀的控件开发者必须了解有关ViewState性能的内容。默认情况下,控件的ViewState将被启用,如果不需要使用ViewState,最好还是将它关闭。以下情况将不再需要ViewState:控件未定义服务器端事件(这时的控件事件均为客户端事件且不参加回送的);控件没有动态的或数据绑定的属性值。其关闭ViewState的方法是将控件的EnableViewState的值设置为“false”,即EnableViewState="false"。
最后,还需要了解一些有关视图状态安全性方面的内容。当查看__VIEWSTATE隐藏域时,看到的只是一些没有意义的字符串。这是.NET框架通过Base64位编码对相关内容编码的结果,默认情况下它们是通过明文方式在客户端和服务器端之间往返传送。在某些情况下,例如涉及密码、帐号、连接字符串等敏感内容时,使用默认方式是很不安全的,为此,.NET框架为ViewState提供了以下两种安全机制。
- 校验机制:可以通过设置EnableViewStateMAC="true"属性来指示.NET框架向ViewState数据中追加一个散列码(该散列码是一种SHA1类型,长度有160位,因此会严重影响执行性能)。在回传事件发生时,将重新建立该散列码,它必须和最初的散列码匹配。通过这种方式,能够有效检验ViewState在传送过程中是否能够被篡改。默认情况下,.NET框架使用SHA1算法来生成ViewState散列代码。此外,也可以通过在machine.config文件中设置<machineKey>来选择MD5算法,例如<machineKey validation="MD5"/>。MD5算法的性能要比SHA1算法好一些,但是同样不够安全。
- 加密机制:使用加密来保护ViewState字段中的实际数据值。首先,必须如上述设置EnableViewStateMAC="true"。然后,将machineKey validation类型设置为3DES,即<machineKey validationKey="AutoGenerate" decryptionKey="AutoGenerate" validation="3DES">,这指示ASP.NET使用3DES加密算法来加密ViewState值。
以上是 视图状态管理概述——《ASP.NET服务器控件开发技术与实例》摘录。
方案
视图状态由 ASP.NET 页框架自动用于保存在各个回发之间必须保留的信息。此信息包括控件的任何非默认值。
您还可以使用视图状态来存储特定于页的应用程序数据。
功能
视图状态是 ASP.NET 页中的存储库,可以存储必须在回发过程中保留的值。页框架使用视图状态在各个回发之间保存控件设置。
可以在您自己的应用程序中使用视图状态完成以下工作:
-
在各个回发之间保存值,而不将这些值存储在会话状态或用户配置文件中。
-
存储您定义的页或控件属性的值。
-
创建一个自定义视图状态提供程序,以便将视图状态信息存储在 SQL Server 数据库或其他数据存储区中。
例如,您可以将信息存储在视图状态中,这样在下次将该页发送到服务器时,代码便可以在页加载事件过程中访问这些信息。有关推荐的使用方法
背景
Web 应用程序是无状态的。每次从服务器请求页时,都会创建网页类的一个新实例。这通常意味着在每次往返过程中会丢失该页及其控件中的所有信息。例如,默认状态下,如果用户将信息输入到 HTML 网页上的文本框中,
该信息会发送到服务器。但是,该信息不会在响应中返回到浏览器。
为了克服 Web 编程的这一固有的局限性,ASP.NET 页框架包含几种状态管理功能,可以在往返过程之间将页和控件值保存到 Web 服务器。其中一种功能便是视图状态。
默认情况下,ASP.NET 页框架使用视图状态在往返过程之间保存页和控件值。在呈现页的 HTML 时,必须在回发过程中保留的页和值的当前状态将被序列化为 Base64 编码字符串。然后,它们将被放入页中的一个或多个隐藏字段。
您可以在代码中使用页的
代码
<div> Label1: <asp:Label ID="Label1" runat="server" Text="取消了视图状态" EnableViewState="false"></asp:Label> <br /> <br /> Label2: <asp:Label ID="Label2" runat="server" Text="视图状态" EnableViewState="true"></asp:Label> <br /> <br /> <asp:Button ID="Button1" runat="server" Text="设置Label1,Label2的值为XXX" onclick="Button1_Click" /> <br /> <asp:Button ID="Button2" runat="server" Text="刷新" /> </div>
后台代码
protected void Button1_Click(object sender, EventArgs e) { Label1.Text = "XXX"; Label2.Text = "XXX"; }
执行页面
注意Label1和Label2值的变化,由于Label2有视图状态所以在刷新后并没有变化。
页面生命周期 是 先加载视图状态里面的值,然后再响应页面事件,所以第二步按钮后都变成“XXX”了,但是此时label1中的视图状态的值并没有改变,在按“刷新”按钮后,Label1只是加载了以前的视图状态值。