• ASP.NET 2.0 压缩ViewState最佳方法,支持UpdatePanel


    作者: 李嘉  日期: 2009-02-09 17:05

    我在一些项目中需要对ViewSate进行压缩,网上查阅了很多资料,发现每个方法方案都不完善,导致压缩ViewState后页面功能出现各种各样的问题,例如以下资料:

    1. 压缩ASP.NET中的ViewState

    2. 压缩ASP.NET中的ViewState的改进方法

    3. 压缩 ViewState 后,与 UpdatePanel 的兼容问题

    但是这些方法的有利有弊,主要是功能上并不完善,导致Ajax的一些应用功能失败,特别是updatepanel中的一些服务端控件的服务端事件无法触发。Google搜索了很多资料没能找到很好的解决方案,于是我研究一下,结合以上链接的几个方法自定义了一套方案,代码如下:

    首先:

    using System.IO;
    using ICSharpCode.SharpZipLib.Zip.Compression;

    ------------------------

            #region 压缩viewstate
            /**/
            /// <summary>
            /// 设定序列化后的字符串长度为多少后启用压缩
            /// </summary>
            private static Int32 LimitLength = 1096;

            /**/
            /// <summary>
            /// 设定压缩比率,压缩比率越高性消耗也将增大
            /// </summary>
            private static Int32 ZipLevel = ICSharpCode.SharpZipLib.Zip.Compression.Deflater.BEST_COMPRESSION;

            /**/
            /// <summary>
            /// 重写保存页的所有视图状态信息
            /// </summary>
            /// <param name="pViewState">要在其中存储视图状态信息的对象</param>
            protected override void SavePageStateToPersistenceMedium(Object pViewState)
            {
                if (Utils.IsMsAjaxCallback(Request))
                {
                    LosFormatter lf = new LosFormatter();
                    using (StringWriter writer = new StringWriter())
                    {
                        lf.Serialize(writer, pViewState);
                        string viewStateString = writer.ToString();
                        byte[] data = Convert.FromBase64String(viewStateString);
                        data = Utils.Compress(data);
                        ScriptManager.RegisterHiddenField(this, "__COMPRESSEDVS", Convert.ToBase64String(data));
                    }
                }
                else
                {
                    //实现一个用于将信息写入字符串的 TextWriter
                    StringWriter mWriter = new StringWriter();

                    //序列化 Web 窗体页的视图状态
                    LosFormatter mFormat = new LosFormatter();

                    //将有限对象序列化 (LOS) 格式化的对象转换为视图状态值
                    mFormat.Serialize(mWriter, pViewState);

                    //将序列化对象转成Base64字符串
                    String vStateStr = mWriter.ToString();

                    //设置是否启用了加密方式,默认情况下为不启用
                    Boolean mUseZip = false;

                    //判断序列化对象的字符串长度是否超出定义的长度界限
                    if (vStateStr.Length > LimitLength)
                    {
                        //对于长度超出阶线的进行加密,同时将状态设为加密方式
                        mUseZip = true;

                        Byte[] pBytes = Compress(vStateStr);

                        //将字节数组转换为Base64字符串
                        vStateStr = System.Convert.ToBase64String(pBytes);
                    }

                    //注册在页面储存ViewState状态的隐藏文本框,并将内容写入这个文本框
                    RegisterHiddenField("__MSPVSTATE", vStateStr);

                    //注册在页面储存是否启用压缩状态的文本框,并将启用状态写入这个文本框
                    RegisterHiddenField("__MSPVSTATE_ZIP", mUseZip.ToString().ToLower());
                }
            }

            /**/
            /// <summary>
            /// 对字符串进行压缩
            /// </summary>
            /// <param name="pViewState">ViewState字符串</param>
            /// <returns>返回流的字节数组</returns>
            public static Byte[] Compress(String pViewState)
            {
                //将存储状态的Base64字串转换为字节数组
                Byte[] pBytes = System.Convert.FromBase64String(pViewState);

                //创建支持内存存储的流
                MemoryStream mMemory = new MemoryStream();

                Deflater mDeflater = new Deflater(ZipLevel);
                ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream mStream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(mMemory, mDeflater, 131072);

                mStream.Write(pBytes, 0, pBytes.Length);
                mStream.Close();

                return mMemory.ToArray();
            }

            /**/
            /// <summary>
            /// 重写将所有保存的视图状态信息加载到页面对象
            /// </summary>
            /// <returns>保存的视图状态</returns>
            protected override Object LoadPageStateFromPersistenceMedium()
            {
                    string viewState = Request.Form["__COMPRESSEDVS"];
                    if (viewState != null)
                    {
                        byte[] data = Convert.FromBase64String(viewState);
                        data = Utils.Decompress(data);
                        LosFormatter lf = new LosFormatter();
                        return lf.Deserialize(Convert.ToBase64String(data));
                    }
                    else
                    {
                        //使用Request方法获取序列化的ViewState字符串
                        String mViewState = this.Request.Form.Get("__MSPVSTATE");
                        //使和Request方法获取当前的ViewState是否启用了压缩
                        String mViewStateZip = this.Request.Form.Get("__MSPVSTATE_ZIP");

                        Byte[] pBytes;

                        if (mViewStateZip == "true")
                        {
                            pBytes = DeCompress(mViewState);
                        }
                        else
                        {
                            //将ViewState的Base64字符串转换成字节
                            pBytes = System.Convert.FromBase64String(mViewState);
                        }

                        //序列化 Web 窗体页的视图状态
                        LosFormatter mFormat = new LosFormatter();

                        //将指定的视图状态值转换为有限对象序列化 (LOS) 格式化的对象
                        return mFormat.Deserialize(System.Convert.ToBase64String(pBytes));
                    }
            }

            /**/
            /// <summary>
            /// 解压缩ViewState字符串
            /// </summary>
            /// <param name="pViewState">ViewState字符串</param>
            /// <returns>返回流的字节数组</returns>
            public static Byte[] DeCompress(String pViewState)
            {
                //将Base64字符串转换为字节数组
                Byte[] pBytes = System.Convert.FromBase64String(pViewState);

                ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream mStream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(new MemoryStream(pBytes));

                //创建支持内存存储的流
                MemoryStream mMemory = new MemoryStream();
                Int32 mSize;

                Byte[] mWriteData = new Byte[4096];

                while (true)
                {
                    mSize = mStream.Read(mWriteData, 0, mWriteData.Length);
                    if (mSize > 0)
                    {
                        mMemory.Write(mWriteData, 0, mSize);
                    }
                    else
                    {
                        break;
                    }
                }

                mStream.Close();
                return mMemory.ToArray();
            }
            #endregion

    附件:

    1. 其中压缩组件: SharpZipLib , 或者直接这里下:Assemblies for .NET 1.1, .NET 2.0, .NET CF 1.0, .NET CF 2.0: Download [228 KB]

    2. 'Utils' 类这里下载: Utils.cs (1.15 kb)

    TrackBack:http://www.mockte.com/rewrite.php/read-79.html

  • 相关阅读:
    天天共写了四本书,如果您使用有问题欢迎反馈
    难道QQ没有办法封?
    一个包含ASP.NET2.0全部登陆控件在典型身份验证的考虑
    数据访问模式二:数据集和数据适配器(传统的数据访问模式)
    数据访问两种模式的比较
    在母版页里使用FindControl的困惑
    有了中文版MSDN2,何必又东奔西走去找资料
    ASP.NET2.0技术详解与应用实例
    ASP.NET2.0新功能之客户端脚本功能
    使用ASP.NET2.0的TreeView控件显示分层数据
  • 原文地址:https://www.cnblogs.com/hdjjun/p/1603727.html
Copyright © 2020-2023  润新知