ASP.NET ViewState详解

对ViewState的误解有可能导致

  1. 泄漏敏感数据
  2. ViewState攻击
  3. 性能低下
  4. 可扩展性低下

ViewState做些什么

  1. 根据Key为每个控件储值
  2. 跟踪ViewState值 初始状态(initial state)的改变
  3. 串行化和并行化存储的数据并存入到一个隐藏字段
  4. 在回发期间自动重建ViewState

ViewState不做什么

  1. 自动持久化类中变量的状态
  2. 对于回发请求,在页面加载的过程中记录状态信息
  3. 在每次请求过程中使系统不重新填充数据
  4. ViewState不为所有的控件服务
  5. 为你煮咖啡

ViewState核心

  1.ViewState储值

ViewState只是一个属性名,它的类型是StateBag。ViewState属性是诸如Page、用户控件(user control)、服务器控件等从System.Web.UI.Control这个基类继承来的。ViewState在Control类中的源码

protected virtual StateBag ViewState { get; }

 

为了维持状态的连续性,或者说提供类似Winform一样的交互体验,Asp.Net服务器控件中的属性储值方式类似下面的代码。

public string Text {
    get {
        return ViewState["Text"] == null ?
             "Default Value!" :
              (string)ViewState["Text"];
    }
    set { ViewState["Text"] = value; }
}

注意当ViewState["Text"]为null时,从Text取到的值将为初始值而非null。所以Text = null这样的赋值将导致重设Text为初值。

 

  2.ViewState跟踪变化(Changes)

stateBag["key"] = "abc";
stateBag.IsItemDirty("key"); // returns false
stateBag.TrackViewState();
stateBag["key"] = "abc";
stateBag.IsItemDirty("key"); // returns true

只有StateBag.TrackViewState()被调用以后,对StateBag中某个项目的赋值才会引发这个项被标记为脏(dirty)。在页面的生命周期中,TrackViewState( )在OnInit( )阶段被调用。

重点是,只有那些被标记为脏的项才会在SaveViewState( )阶段被保存到隐藏字段中。

 

  1.序列化和反序列化

控 件可能拥有子控件。页面是一棵控件树,而Page(或者说ASPX页面)正是这棵树的根。控件树中的每一个控件都拥有自己的ViewState属性,因为 它继承自System.Web.UI.Control。Asp.Net通过递归调用控件树上每一个控件的SaveViewState( )方法来建立一棵数据树(data tree or object tree),这棵数据树与控件树不同在于,它保存的是SaveViewState( )返回的object对象。而SaveViewState( )方法返回的object将被序列化后存储到_ViewState这个隐藏字段中。

 

  2.自动恢复数据

页 面的生命周期中,在加载ViewState之前(即调用控件的LoadViewState( )方法之前)StateBag可能已经有值了,这些值可能来自ASPX中持久化的属性值,也可能是在LoadViewStae( )被调用之前(即OnInit事件之前)被人为地设置了值(即人为地为StateBag增加了StateItem)。如果某个控件在 LoadViewState( )被调用前存入了一个在LoadViewState( )期间会处理到的相同的键,那么之前存入的项可能会被覆盖。原因是LoadViewState( )会加载上一次请求中被标记为脏的项。

英文原文出处:http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx

原文地址:https://www.cnblogs.com/wsion/p/3460523.html