Create new account I forgot my password    

How to compress viewstate in ASP.NET 2.0
Rating: 12 user(s) have rated this article Average rating: 4.2
Posted by: Suprotim Agarwal, on 7/30/2007, in category "ASP.NET 2.0 & 3.5"
Views: this article has been read 15891 times
Abstract: This article demonstrates how to extend the functionality of the new System.IO.Compression namespace to compress and decompress viewstate information in ASP.NET 2.0 pages.

How to compress ViewState In ASP.NET
 
Http is a stateless protocol. Hence the ‘page-state-information’ is not saved between postbacks. In ASP.NET, viewstate is the means of storing the state of server side controls between postbacks. It contains a snapshot of the contents of a page. The information is stored in HTML hidden fields.
The viewstate is quiet handy in most cases as it does a lot of work for you in saving the state of controls. However it comes with a cost. If your page contains a lot of controls holding a large amount of data, you can imagine the load when this data is transferred to and from the browser on each postback. It gradually increases the size of your page, thereby leading to performance issues. Well you can get around this problem by disabling viewstate for controls, where maintaining state is not required (EnableViewState=false). However, in scenarios, where maintaining the state of controls is required, compressing viewstate helps improve performance.
Using System.IO.Compression
 
In ASP.NET 1.1, developers used custom compression tools like ICSharpCode.SharpZipLib  to compress viewstate. ASP.NET 2.0 provides us with the System.IO.Compression namespace, which contains classes with functionality to compress and decompress streams. This namespace contains two classes called DeflateStream and GZipStream that provides methods and properties to compress and decompress streams.
Compressing/Decompressing using GZipStream
 
The compression functionality in GZipStream is exposed as a stream. In the code displayed below, we will create a class called ViewStateCompressor that contains two methods :
Compress(byte[] array) - Accepts a decompressed bytearray, compresses it and returns a compressed bytearray.
Decompress(byte[] array) – Accepts compressed bytearray, decompresses it and returns a decompressed bytearray.
The code has been commented to help you understand each method.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.IO.Compression;
 
///<summary>
/// Summary description for ViewStateCompressor
///</summary>
public class ViewStateCompressor
{
      public ViewStateCompressor()
      {
            //
            // TODO: Add constructor logic here
            //
      }
 
    public static byte[] CompressViewState(byte[] uncompData)
    {
        using (MemoryStream mem = new MemoryStream())
        {
            CompressionMode mode = CompressionMode.Compress;
            // Use the newly created memory stream for the compressed data.
            using (GZipStream gzip = new GZipStream(mem, mode, true))
            {
                //Writes compressed byte to the underlying
                //stream from the specified byte array.
                gzip.Write(uncompData, 0, uncompData.Length);
            }
            return mem.ToArray();
        }      
    }
 
    public static byte[] DecompressViewState(byte[] compData)
    {
        GZipStream gzip;
        using (MemoryStream inputMem = new MemoryStream())
        {
            inputMem.Write(compData, 0, compData.Length);
            // Reset the memory stream position to begin decompression.
            inputMem.Position = 0;
            CompressionMode mode = CompressionMode.Decompress;
            gzip = new GZipStream(inputMem, mode, true);
        }
 
        using (MemoryStream outputMem = new MemoryStream())
        {
            // Read 1024 bytes at a time
            byte[] buf = new byte[1024];
            int byteRead = -1;
            byteRead = gzip.Read(buf, 0, buf.Length);
            while (byteRead <= 0)
            {
                //write to memory stream
                outputMem.Write(buf, 0, byteRead);
                byteRead = gzip.Read(buf, 0, buf.Length);
            }
            gzip.Close();
            return outputMem.ToArray();
        }
    }
}
 
Utilizing the ViewStateCompressor class
 
Once we have created the functionality of compressing and decompressing viewstate, its time to use this functionality in our webpages. For this, create a CustomPage which inherits from System.Web.UI.Page. In the CustomPage, you will need to override the LoadPageStateFromPersistenceMedium() and SavePageStateToPersistenceMedium() to serialize and deserialize viewstate. We require this customization because we are compressing the viewstate.  All the other web pages in the application will inherit from this BasePage.
The LoadPageStateFromPersistenceMedium() method has been overridden here to decompress the bytes stored in hidden field “_CustomViewState”. The steps performed are as follows :
·         The compressed viewstate stored in this field is encoded as Base64 string.
·         The Convert.FromBase64String(viewState) converts it into byte array.
·         It’s time to call the DecompressViewState() method we created earlier.
·         This method returns a bytearray containing decompressesed data which is converted back to Base64 string.
·         Finally the LosFormatter class is used to deserialize the view state.
The SavePageStateToPersistenceMedium() method accepts a ViewState object. The Serialize() method of the LosFormatter class accepts a stream and the viewstate object. If you have already observed, we are performing a reverse operation of what we did in the LoadPageStateFromPersistenceMedium() method. We will first serialize, compress and then encode data in Base64. This Base64 string is then saved into the “_CustomViewState” hidden field.
The code has been given below :
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
 
///<summary>
/// Summary description for CustomPage
///</summary>
public partial class CustomPage : Page
{
      public CustomPage()
      {
            //
            // TODO: Add constructor logic here
            //
      }
 
    // Serialize view state
    protected override void SavePageStateToPersistenceMedium(object pageViewState)
    {
        LosFormatter losformatter = new LosFormatter();
        StringWriter sw = new StringWriter();
        losformatter.Serialize(sw, pageViewState);
        string viewStateString = sw.ToString();
        byte[] b = Convert.FromBase64String(viewStateString);
        b = ViewStateCompressor.CompressViewState(b);
        ClientScript.RegisterHiddenField("__CUSTOMVIEWSTATE", Convert.ToBase64String(b));
    }
 
    // Deserialize view state
    protected override object LoadPageStateFromPersistenceMedium()
    {
        string custState = Request.Form["__CUSTOMVIEWSTATE"];
        byte[] b = Convert.FromBase64String(custState);
        b = ViewStateCompressor.DecompressViewState(b);
        LosFormatter losformatter = new LosFormatter();
        return losformatter.Deserialize(Convert.ToBase64String(b));
    }
 
  
}
 
There you go!! Use these classes and hopefully your ViewState size will be reduced by 30-40%.
References
There are a number of good resources I referred to for this article. A few of them are:
http://www.dotnetbips.com/articles/22d33d11-1a75-42c8-bbf6-ca1a345d3fcf.aspx
http://www.codeproject.com/aspnet/ViewStateCompression.asp
http://www.eggheadcafe.com/articles/20040613.asp
http://msdn2.microsoft.com
Conclusion
This article introduced you to a new namespace System.IO.Compression in ASP.NET 2.0. We went through the classes provided in this namespace. The GzipStream class contains functionality to compress and decompress streams. We used it to compress and decompress viewstate to improve performance of our web applications. I hope this article was informative and I thank you for viewing it.
 







Follow me on twitter

Page copy protected against web site content infringement by Copyscape


How would you rate this article?

User Feedback
Comment posted by Shameek Bain on Wednesday, March 19, 2008 7:48 AM
I think the while condition is wrong here. It should be as while (byteRead > 0) instead of while (byteRead <= 0)


while (byteRead <= 0)
            {
                //write to memory stream
                outputMem.Write(buf, 0, byteRead);
                byteRead = gzip.Read(buf, 0, buf.Length);
            }
Comment posted by Michael Mason on Monday, April 14, 2008 9:39 AM
Good idea. However, this may not work so well if pages use UpdatePanels for partial updates.
Comment posted by Thomas Hansen on Saturday, April 19, 2008 5:39 PM
Way to go :)))
Comment posted by jhjhh on Friday, May 30, 2008 7:12 AM
jhjhg
Comment posted by Ragunathan.M on Saturday, July 12, 2008 6:29 AM
ya nice idea. this is very useful for me
Comment posted by Jeff Bragin on Tuesday, July 07, 2009 4:21 PM
IT DOES NOT WORK.

the minute i enabled paging on a gridview, I got an error "can't read a close stream" around this line:             byteRead = gzip.Read(buf, 0, buf.Length);

Comment posted by Wade on Wednesday, August 19, 2009 9:35 PM
Yeah I'm getting the same problem, "Cannot access a closed Stream" around the same line. Any suggestions?
Comment posted by Yogish M S on Friday, October 09, 2009 3:49 AM
try without using Using,

Post your comment
Name:
E-mail: (Will not be displayed)
Comment:
Insert Cancel