zoukankan      html  css  js  c++  java
  • ASP.NET之ViewState

    什么是ViewState?

       在asp时代, 大家都知道一个html控件的值,比如input 控件值,当我们把表单提交到服务器后, 页面再刷新回来的时候, input里面的数据已经被清空. 这是因为web的无状态性导致的, 服务端每次把html输出到客户端后就不再与客户端有联系.
       asp.net巧妙的改变了这一点. 当我们在写一个asp.net表单时, 一旦标明了 form runat=server,那么,asp.net就会自动在输出时给页面添加一个隐藏域

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

       那么,有了这个隐藏域,页面里其它所有的控件的状态,包括页面本身的一些状态都会保存到这个控件值里面.每次页面提交时一起提交到后台,asp.net对其中的值进行解码,然后输出时再根据这个值来恢复各个控件的状态. 我们再看这个控件的value值,它可能类似如下的形式:Oz4+O2w8aTwxPjs+O2w8.... 

    很多人会认为这是加密的信息,其实不是, Microsoft仅仅是给各个控件和页面的状态存入适当的对象里面,然后把该对象序列化, 最后再做一次base64编码,直接赋值给viewstate控件.

       说到这,想必你一定想看看这个viewstate里面到底存了哪些东西, 嗯,你是可以写一个base64 to string的转换代码来实现.不过,viewstate是有层次之分的,普通的转换后,你看到的也是很乱的文字. 这里提供了一个专门转换viewstate值的地方 http://www.wilsondotnet.com/Demos/ViewState.aspx .你可以去将自己的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.页面级别

    <%@ Page EnableViewState ="False" %> 
    or 
    <%@ Page EnableViewState ="True" %>
    2.控件级别
    <asp:TextBox id="txtCode" runat="server” EnableViewState="false" />
    or
    <asp:TextBox id="txtCode" runat="server" EnableViewState="true" />
    3.应用程序级别
    <pages enableViewState="false" />
    or
    <pages enableViewState="true" />
    4.机器级别
    <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"/>


    转自:http://www.yongfa365.com/Item/ASP.net-View-State.html

             http://www.cnblogs.com/yzxchoice/archive/2006/09/08/498499.html

  • 相关阅读:
    支持向量机(Support Vector Machine / SVM)
    k-近邻算法(KNN)
    STM32端口模式配置——上拉、下拉、模拟、浮空输入;推挽、开漏、复用输出
    Catia V5-6R2017破解版|Catia V5-6R2017下载|安装破解步骤
    在远方
    快递 10 年,逆袭为王
    “四通一达”本一家,这家人是如何“承包”中国快递半壁江山的?
    JavaScript中的内存释放
    常见的几种JavaScript内存泄露
    span(行级元素)在不定高的div(块级元素)中垂直居中的方法
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207114.html
Copyright © 2011-2022 走看看