Compressing ViewState of your Application
.Net framework has an entire namespace for compression - System.IO.Compression. GZipStream is the class used for Compression and Decompression.
.Net Framework 2.0, exposes a new class called PageStatePersister. This class is used to override and customize how you can Load and Persist the ViewState. This is a huge bonus for people who want to persist the ViewState out of the client side Html and move it to server side Cache or Database.
So this example will create a new class "ViewStateCompressor" which inherits from PageStatePersister. There are 2 methods of PageStatePersister you will need to override Load() and Save(). This class will Compress the ViewState on Save(), so the ViewState sent to the Client side is small and it will Decompress on Load().
/// <summary>
/// Overridden by derived classes to serialize persisted state information when a <see cref="T:System.Web.UI.Page"></see> object is unloaded from memory.
/// </summary>
public override void Save()
{
using (StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture))
{
StateFormatter.Serialize(writer, new Pair(base.ViewState, base.ControlState));
byte[] bytes = Convert.FromBase64String(writer.ToString());
using (MemoryStream output = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(output, CompressionMode.Compress, true))
{
gzip.Write(bytes, 0, bytes.Length);
}
base.Page.ClientScript.RegisterHiddenField(Constants.ViewStateFieldName, Convert.ToBase64String(output.ToArray()));
}
}
}
/// <summary>
/// Overridden by derived classes to deserialize and load persisted state information when a <see cref="T:System.Web.UI.Page"></see> object initializes its control hierarchy.
/// </summary>
public override void Load()
{
byte[] bytes = Convert.FromBase64String(base.Page.Request.Form[Constants.ViewStateFieldName]);
using (MemoryStream input = new MemoryStream())
{
input.Write(bytes, 0, bytes.Length);
input.Position = 0;
using (GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true))
{
using (MemoryStream output = new MemoryStream())
{
byte[] buff = new byte[64];
int read = -1;
read = gzip.Read(buff, 0, buff.Length);
while (read > 0)
{
output.Write(buff, 0, read);
read = gzip.Read(buff, 0, buff.Length);
}
Pair p = ((Pair)(StateFormatter.Deserialize(Convert.ToBase64String(output.ToArray()))));
base.ViewState = p.First;
base.ControlState = p.Second;
}
}
}
}
I created a BasePage which inherits from System.Web.UI.Page and all the pages in the application will inherit from this BasePage. In the BasePage, you will need to override the PageStatePersistor and return our ViewStateCompressor class
public class BasePage : System.Web.UI.Page
{
private ViewStateCompressor _viewStateCompressor;
public BasePage() : base()
{
_viewStateCompressor = new ViewStateCompressor(this);
}
protected override PageStatePersister PageStatePersister
{
get
{
return _viewStateCompressor;
}
}
}
Inherit the BasePage in your pages and you should get ViewState Compression. My test has shown the ViewState typically reduces by 30-40%. Try the code provided below.