zoukankan      html  css  js  c++  java
  • 有关视图状态(ViewState)的一些问题

    ASP.NET的ViewState是一个毁誉参半的设计。虽然很少有人真的讲清楚里面存的是什么东西,而且它到底将怎么影响我们的开发。但是大家目前的几点共识如下

    1. 能不用它的时候就不用,以免降低性能。

    要关闭它有三种方式

    1.1 通过在web.config中将所有页面的视图状态都关闭掉

    1.2 在某个特定页面中将其关闭

    1.3 在某个特定控件上将其关闭

    2. 如果非得用它,但又顾忌到性能和网络流量。那么可以选择压缩它。下面这个文档有详细的介绍。

    http://www.cnblogs.com/webabcd/archive/2008/08/21/672587.html

    大致的代码如下。主要重写了两个方法,SavePageStateToPersistenceMedium和LoadPageStateFromPersistenceMedium

    【注意】这里既然是可以控制保存和加载行为,那么从道理上说,也可以把这些状态保存到其他地方,例如Session中。(手机页面通常这么做)

    【注意】同样的道理,这里也可以进行加密和解密操作

    protected override void SavePageStateToPersistenceMedium(object state) //这里传过来的参数就是那些视图状态值
    {
        LosFormatter formatter = new LosFormatter();
        StringWriter writer = new StringWriter();
        formatter.Serialize(writer, state);
    string viewState = writer.ToString();
    byte[] data = Convert.FromBase64String(viewState);//一般都是用BASE64进行编码
    byte[] compressedData = ViewStateHelper.Compress(data);
    string str = Convert.ToBase64String(compressedData);
        ClientScript.RegisterHiddenField("__MYVIEWSTATE", str);//目前还是放在页面里面。只不过是另外一个隐藏域而已。
    }

    protected override object LoadPageStateFromPersistenceMedium()
    {
    string viewstate = Request.Form["__MYVIEWSTATE"];
    byte[] data = Convert.FromBase64String(viewstate);
    byte[] uncompressedData =
        ViewStateHelper.Decompress(data);
    string str = Convert.ToBase64String(uncompressedData);
        LosFormatter formatter = new LosFormatter();
    return formatter.Deserialize(str);
    }

    为了方便,这里编写了一个用来压缩和解压缩的帮助类(ViewStateHelper)

    public static byte[] Compress(byte[] data)
    {
        MemoryStream ms = new MemoryStream();
        GZipStream stream = new GZipStream(ms, CompressionMode.Compress);
        stream.Write(data, 0, data.Length);
        stream.Close();
    return ms.ToArray();
    }

    public static byte[] Decompress(byte[] data)
    {
        MemoryStream ms = new MemoryStream();
        ms.Write(data, 0, data.Length);
        ms.Position = 0;
        GZipStream stream = new GZipStream(ms, CompressionMode.Decompress);
        MemoryStream temp = new MemoryStream();
    byte[] buffer = new byte[1024];
    while (true)
    {
    int read = stream.Read(buffer, 0, buffer.Length);
    if (read <= 0)
    {
    break;
            }
    else
    {
                temp.Write(buffer, 0, buffer.Length);
            }
        }
        stream.Close();
    return temp.ToArray();
    }

    3. 除了可以压缩和加密,还有朋友提出,为了提高页面对于搜索引擎的友好性,应该将ViewState从表单的顶部移动到底部。这是一个很有意思的想法,下面这个文章讲述了大致怎么做

    http://blog.csdn.net/lee576/archive/2008/11/01/3200258.aspx

    这个代码的工作原理其实比较简单,它是重写了页面的Render方法,并且强制将那个视图状态的input移动到了底部。

    //ViewState的Html标记的正则表达式
           private static readonly Regex viewStateRegex = new Regex(@"(<input type=""hidden"" name=""__VIEWSTATE"" id=""__VIEWSTATE"" value=""/w(.*)"" />)", RegexOptions.Multiline | RegexOptions.Compiled);
           //</form>标记的正则表达式
           private static readonly Regex endFormRegex = new Regex(@"</form>", RegexOptions.Multiline | RegexOptions.Compiled);
           protected override void Render(HtmlTextWriter writer)
           {
               System.IO.StringWriter stringWriter = new System.IO.StringWriter();
               HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
               base.Render(htmlWriter);

               string html = stringWriter.ToString();
               Match viewStateMatch = viewStateRegex.Match(html);

               string viewStateString = viewStateMatch.Captures[0].Value;//找出ViewState的Html标记
               html = html.Remove(viewStateMatch.Index, viewStateMatch.Length);//替换掉ViewState的html标记

               Match endFormMath = endFormRegex.Match(html, viewStateMatch.Index);
               html = html.Insert(endFormMath.Index, viewStateString);//将ViewState的Html标记插入到</form>标记之前
               writer.Write(html);

           }

    4. ViewState对象

    ViewState不光是控件或者页面的一个属性,它也是一个特殊的API。我们可以通过ViewState[“VarName”]=value这种方式对其进行读写。但这个功能显然也是受到了页面级别的那个EnableViewState开关的控制。

    5. 控件状态

    因为ViewState可以被禁用,但是如果服务器控件需要保留自己的一些值,那么就可能会用到控件状态。有兴趣的朋友可以参考我另外一篇博客

    http://www.cnblogs.com/chenxizhang/archive/2009/04/02/1427827.html

  • 相关阅读:
    需求规格说明书
    需求规格说明书模板0.2版本
    需求规格说明书模板0.1版本
    万事开头难,团队一起盘!!
    工程开始了!(2019-03-04)
    SpringBoot RESTful API返回统一数据格式还不懂?
    Springboot读取配置文件中的属性
    java本地缓存的使用
    解决github访问不了和慢的问题2021-06-27
    Oracle DDL
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1428295.html
Copyright © 2011-2022 走看看