Click here to Skip to main content
Click here to Skip to main content
Go to top

Minimizing VIEWSTATE Size and Customization of Server Reponse Via HTTPMODULE

, 19 Oct 2010
Rate this:
Please Sign up or sign in to vote.
VIEWSTATE is one of the primary factors which affect your web application. In this article, I will try to highlight the way to compress VIEWSTATE and customize server response using HTTPMODULES

Introduction

First of all, I will say hi to all. It is my very first attempt to write an article on any forum. I read somewhere that you can check that whether you are learning or not if "you are making mistakes provided everytime you make a new mistake". Well, I make lots of mistakes more than normal people Smile | :) . Anyway in this article, if you see some area of improvement, then please let me know so that next time I just make a new mistake Smile | :) .

Basically, this article will talk about VIEWSTATE and server response customization techniques. Well, you know what is VIEWSTATE and why ASP.NET introduced it. VIEWSTATE (as the name tells) keep the state of the controls rendered by the server on client agents (e.g. Web Browsers, etc.) so that on next postback, it can inform the server about the previous state of the page control hierarchy, etc. All in all, what we can say is that it is a very important page element to keep state information as well as some other information to server (e.g. whether page is POSTBACK, etc.).

There are some other ways to keep the state information like server session but this consumes the server resources and may not be scalable solutions. Lots of people use the first option that is VIEWSTATE to maintain the state information of server controls. VIEWSTATE is saved in a hidden field named __VIEWSTATE.

One of the big problems with VIEWSTATE is that it travels with each request and response and consumes precious bandwidth. So, in this article, we will look around for a way to minimize the VIEWSTATE size. I have developed a little HTTPMODULE to customize the Page rendered content.

Background

It is better that you just have a look at these to better understand what I am trying to do here

Let's Have A Look Inside Page Class

In order to fully understand the concept and use it in your own scenario, I feel it is important to give you some inside idea how Page class is maintaining VIEWSTATE. If you are already familiar with it, you can skip this section.

Page class provides a number of virtual functions and properties to override. In our case, we just need to override one such property of Page class, i.e. PageStatePersister. Internal Implementation of Page's PageStatePersister property is shown below:

  1  //we need to override this property and use own PageStatePersister to save and 
  2  load controls state (VIEWSTATE/CONTROLSTATE) 
  3  protected virtual PageStatePersister PageStatePersister
  4  {
  5      get
  6      {
  7          if (this._persister == null)
  8          {
  9              PageAdapter pageAdapter = this.PageAdapter;
 10              if (pageAdapter != null)
 11              {
 12                  this._persister = pageAdapter.GetStatePersister();
 13              }
 14              if (this._persister == null)
 15              {
 16                  this._persister = new HiddenFieldPageStatePersister(this);
 17              }
 18          }
 19          return this._persister;
 20      }
 21  }

As highlighted in the above code snippet, PageAdapter is used to get PageStatePersister. Default persister is HiddenFieldPageStatePersister.

  1  //Virtual function for Page Adapter Abstract class
  2  public virtual PageStatePersister GetStatePersister()
  3  {
  4      return new HiddenFieldPageStatePersister(base.Page);
  5  }

As far as my knowledge is concerned, there are two Page State Persisters provided by the ASP.NET FCL (Framework Class Library).

  • HidenFieldPageStatePersister (Default):
    It will use a hidden field such as _VIEWSTATE to keep the state in Base64 encoded string.
  • SessionPageStatePersister: It is used to save the state in Session by using server resources.

How to Use this Code

Here in this section, I will give you a step by step demo about how we can achieve our final goal, i.e., to build custom State Persister to save and load compressed VIEWSTATE.
  1   public class ZipPageStatePersister : PageStatePersister
  2      {
  3          public ZipPageStatePersister(Page _page);
  4  
  5          public static string CompressData(byte[] data);
  6          public static byte[] Decompress(byte[] data);
  7          public override void Load();
  8          public override void Save();
  9      }

In the above code snippet, I just gave you an outline of my custom PageStatePersister Type. It has two abstract methods, Load and Save implementation along with two static custom Compression/DeCompression methods. Let's have a look at each one by one...

  1  public override void Save()
  2    {
  3        if (this.ViewState != null || this.ControlState != null)
  4        {
  5           using (StringWriter _writer = new StringWriter())
  6           {
  7             Pair _pair = new Pair(this.ViewState, this.ControlState);
  8  
  9             LosFormatter _formatter = new LosFormatter();
 10             _formatter.Serialize(_writer, _pair);
 11  
 12            string _zippedData = 
 13             CompressData(Convert.FromBase64String(_writer.ToString()));
 14  
 15             this.Page.ClientScript.RegisterHiddenField("_VSTATE 
 16                      , _zippedData);
 17           }
 18        }
 19    }
 20

In the above code, we are checking that VIEWSTATE or ControlSate are not both null. And we are using LOSFormatter for serialization of our states. One of the very important points to note is that we are registering hidden fields to our page instance, the first parameter is the name of that hidden field and the second parameter is value (in our case, it custom serialize state compressed and then encoded in Base64 string).

  1  public override void Load()
  2          {
  3              if (!string.IsNullOrEmpty(this.Page.Request.Form["_VSTATE"]))
  4              {
  5                byte[] bytes =Convert.FromBase64String(this.Page.Request.Form[
  6  _VSTATE"]);
  7  
  8            byte[] _decompressed = Decompress(bytes);
  9            StringReader _reader = new 
 10  StringReader(Convert.ToBase64String(_decompressed));
 11  
 12              LosFormatter _formatter = new LosFormatter();
 13              Pair _pair = _formatter.Deserialize(_reader.ReadToEnd()) as Pair;
 14  
 15                  if (_pair != null)
 16                  {
 17                      this.ViewState = _pair.First;
 18                      this.ControlState = _pair.Second;
 19                  }
 20              }
 21          }
 22

When our page is loaded (in the case of POSTBACK), then hidden field "_VSTATE" (first argument of RegisterHiddenField method described above); is keeping the state of our Page. What is your guess - how we will load that state, you are guessing hmmmmm.... yes, you are right. It is load method that will do the trick this time. In the above code, you can see that we are doing exactly the opposite of what we did in the save method. First, we are decoding state information from Base64 to byte array and decompressing it using GzipCompressor. And the next few lines, I don't think need explanation. Quite simple, ahhhhhhha?

OK, I am not showing compression and decompression code here because in those methods, I am just using GZipCompressor class. Anyway, now we are ready to override Page's property PageStatePersister. And here is the code...

  1  public partial class WebForm1 : System.Web.UI.Page
  2      {
  3          private ZipPageStatePersister _zipperPSP;
  4  
  5          protected WebForm1()
  6          {
  7              this._zipperPSP = new ZipPageStatePersister(this);
  8          }
  9  
 10          /// <summary>
 11          /// Overriding to use our custom PageStatePersister
 12          /// </summary/>
 13          protected override PageStatePersister PageStatePersister
 14          {
 15              get
 16              {
 17                  return _zipperPSP;
 18                  //return base.PageStatePersister;
 19              }
 20          }
 21      }
 22

We are creating a private member of our newly created State Persister class and returning it in PageStatePersister instead of default PageStatePersister i.e. HiddenFieldPageStatePersister; Well we are done here. Now when you will view your page in browser, you can see a hidden field name _VSTATE containing the state information. But you will probably notice that old _VIEWSTATE hidden field is still there, but empty in this case.

Getting Rid of _VIEWSTATE Field

When I saw this behavior, then the first solution that came into my mind was to use HTTPHANDLER. But we cannot write to HttpApplication.Context.Resoponse.OutputStream. Fortunately, I found somebody has already encountered it. The solution is to keep the client stream and then create own customized stream to write the output. I will not explain the whole procedure here as you can find, but I will just explain what I did to remove _VIEWSTATE field.

StdViewStateRemover is implementing IHttpModule and VSStream is nested type extending Stream class to customize the output in its write method

Here is the write method that I used to get rid of standard _VIEWSTATE field.

  1  public override void Write(byte[] buffer, int offset, int count)
  2  {
  3   System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding();
  4   System.Text.StringBuilder strBuff = new 
  5  System.Text.StringBuilder(utf8.GetString(buffer));
  6  
  7  //Regular Expression to Find ViewState in Response
  8  Regex reg = 
  9  new Regex("<input type=\"text\" name=\"__VIEWSTATE\"[\\w\\W]* />");
 10  
 11  string _temp = reg.Replace(strBuff.ToString(), string.Empty);
 12  strBuff.Remove(0, strBuff.Length - 1).Append(_temp);
 13  
 14  mSR.Write(strBuff.ToString());
 15  }

HTTPModule Registering in web.config

In order to HttpModule, you have to register module in web.config:

  1  <httpmodules>
  2        <add type="WebApplication1.StdViewStateRemover, WebApplication1 " 
  3  name="StdViewStateRemover">
  4      </add>
  5  </httpmodules>
  6

Now when you view the page in browser, then in source, you can easily verify that _VSTATE exists with compressed Base64 encoded string.

Points of Interest

OK. That's it for now. But you have got an idea how you can extend this HttpModule to customize page response. If you don't want to extend PageStatePersister, then you can also compress viewstate in Write method of custom output stream.

Now, I am trying to find out how much this solution is promising for me to utilize in large VIEWSTATE case and how much it has an impact on my server's performance while compressing/decompressing.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Muhammad Shoaib Raja
Software Developer Pakistan Revenu Automation Ltd. (PRAL)
Pakistan Pakistan
I am passionate web developer and mostly works in ASP.NET and Adobe Flex applications. Now my keen of learning is driving me toward Node.js and believe me, i truly love it.
 
I have just started my blog and you can find it Here

Comments and Discussions

 
SuggestionDatabase / Cache instead of Compression PinmemberhAshishNangla25-Jul-11 8:34 
GeneralWrong Regular Expression Pinmemberjojokim19-Oct-10 10:38 
GeneralRe: Wrong Regular Expression PinmemberMShoab19-Oct-10 22:06 
QuestionDoes this work with an AJAX enabled Page? PinmemberWhiteKnight19-Oct-10 10:25 
AnswerRe: Does this work with an AJAX enabled Page? PinmemberMShoab19-Oct-10 21:29 
GeneralRe: Does this work with an AJAX enabled Page? PinmemberWhiteKnight20-Oct-10 4:36 
GeneralRe: Does this work with an AJAX enabled Page? PinmemberMShoab20-Oct-10 5:15 
GeneralRe: Does this work with an AJAX enabled Page? PinmemberWhiteKnight20-Oct-10 5:33 
GeneralRe: Does this work with an AJAX enabled Page? PinmemberMuhammad Shoaib Raja20-Oct-10 6:01 
GeneralRe: Does this work with an AJAX enabled Page? PinmemberWhiteKnight20-Oct-10 7:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 19 Oct 2010
Article Copyright 2010 by Muhammad Shoaib Raja
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid