理解Asp.net中的View state

什么是ViewState?
对于ViewState,我们有许多的误解。Viewstate不保存控件,而是去保存form中对应ID控件的值,特别是那些由于他们没有和form一起post 而在页面回传时会丢失的控件的值。viewstate一般不要用来保存session或在页面间传输数据。在页面回传后,viewstate不能用来动态地创建页面的控件。他在页面回传之后不回复控件的值。甚至一个控件的viewstate被禁止了,在页面回传后,控件的值仍然不会丢失,比如textbox,dropdownlist控件。那什么是viewstate呢?viewstate保存最后一次在服务器上处理的页面状态。他不能保存那些被动态改变的控件的值。

viewstate是如何工作的?
所有的服务器端控件都有一个ViewState属性。如果他是enable的,这个控件的viewstate就起作用了。那viewstate是在哪里,是如何存储的呢?当一个页面第一次加载,所有的控件被序列化到viewstate,保存在一个叫_ViewState的隐藏form字段里。这个隐藏字段对应服务器端的ViewState对象。页面的ViewState使用System.Web.UI.StateBag对象存储键值对。当一个回传发生,页面反序列化ViewState然后恢复所有的控件。页面中保存控件的ViewState以base 64 编码格式存储成name - value。当一个页面重新加载,会调用两个和ViewState相关的方法, LoadViewState 和SaveViewState。下面是我的一个页面中的_ViewState隐藏字段。

< input type = " hidden "  name = " __VIEWSTATE "  value = " dNrATo45Tm5QzQ7Oz8AblWpxPjE9MMl0Aq765QnCmP2TQ== "   />

启用和禁止ViewState
在默认情况下,所有服务器控件的viewstate开启状态,通过以及几种途径来禁止。
1.页面级别
2.控件级别
3.应用程序级别
4.机器级别
页面级别禁止的方法是在页面的开始写入

<% @ Page EnableViewState  = " False "   %>  
or 
<% @ Page EnableViewState  = " True "   %>

控件级别是

< asp:TextBox id = " txtCode "  runat = " server” EnableViewState= " false "  />
or
< asp:TextBox id = " txtCode "  runat = " server "  EnableViewState = " true "   />

程序级别是在web.config中

< pages enableViewState = " false "   />
or
< pages enableViewState = " true "   />

机器级别是在machine.config中

< pages enableViewState = " true "  enableViewStateMac = " true "  ...  />
or
< pages enableViewState = " false "  ...  />

在viewstate中保存和取出值
viewstate能处理以下的类型
基本类型,基本类型数组,ArrayList 和Hashtable,任何可以序列化的对象。

以下代码是将ArrayList存到viewstate中并取出

ArrayList obj  =   new  ArrayList();
// Some code
ViewState[ " ViewStateObject " =  obj;
  
obj = ViewState["ViewStateObject"];

性能问题
为了更好的页面呈现性能,viewstate应该尽可能的小。要记住Viewstate中的数据会占用很多的网络带宽。因此我们要谨慎的利用viewstate。如果页面和控件不需要回传,那么就要禁止viewstate属性。通常在aspx页面之外保存Viewstate会取得更好的性能表现。为了达到这个目的,我们可以使用SavePageStateToPersistenceMedium 和LoadPageStateFromPersistenceMedium 这两个方法。在web.config或machine.config设置来禁止某个程序的所有页面或全部程序页面的viewstate。

注意只有控件包含在<form runat=server>里才能存储viewstate。然而即使页面所有的viewstate被禁止,页面仍然在viewstate中保存20字节的数据,用来在回传时为相应的控件分配viewstate中的数据。所以当页面完全没有回传,移去runat="server"能减少20字节的数据。如果有很多这样的页面,20字节的节省也能在一定程度上减少带宽。viewstate应该在必要的时候使用。在DataGrid和DataRepeater这样的控件中要避免使用viewstate,因为这些控件的viewstate占用数据相当大。

下面我提供一个简单的用于计算页面viewstate大小的方法。创建一个MasterPageBase 类,然后其他所有的页面都要继承他。

public   class  MasterPageBase: System.Web.UI.Page
{
  
protected override void OnPreRender(EventArgs e)
  
{
    
object viewStateObject = HttpContext.Current.Request["__VIEWSTATE"];
    
if (viewStateObject == null)
      HttpContext.Current.Trace.Warn(
"The ViewState Size is:""0");
    
else
      HttpContext.Current.Trace.Warn(
"The ViewState Size is:",
        HttpContext.Current.Request[
"__VIEWSTATE"].Length.ToString());
    
base.OnPreRender(e);
  }

}

安全问题
可以采取两个措施来避免viewstate被仿冒
使用EnableViewStateMac属性
 ViewState中的内容加密
EnableViewStateMac会进行一个机器授权验证(MAC),这应在页面级别或程序级别使用。当设置时,这个属性会在viewstate呈现之前附加一个viewstate的hash值。当回传发生时,hash值会被重新计算和核对。如果他们不匹配,页面会拒绝显示,这样就确保了viewstate没有被纂改。

在machine.config中设置对viewstate内容的加密

< machineKey  validation ="3Des"   />  or  < machineKey  validation ="SHA1" />

viewstate容易出错的地方
当将一个页面的控件传输到另外一个页面(第二个页面)时,通常会出现错误。解决方法是在第二个页面中将viewstate禁用。


 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值