Click here to Skip to main content
11,649,522 members (76,287 online)
Click here to Skip to main content

Minimizing VIEWSTATE Size and Customization of Server Reponse Via HTTPMODULE

, 19 Oct 2010 CPOL 21.3K 205 14
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 VIEWSTATEand server response customization techniques. Well, you know what is VIEWSTATEand 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 VIEWSTATEto maintain the state information of server controls. VIEWSTATEis saved in a hidden field named __VIEWSTATE.

One of the big problems with VIEWSTATEis 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 VIEWSTATEsize. I have developed a little HTTPMODULEto 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 Pageclass is maintaining VIEWSTATE. If you are already familiar with it, you can skip this section.

Pageclass provides a number of virtual functions and properties to override. In our case, we just need to override one such property of Pageclass, i.e. PageStatePersister. Internal Implementation of Page's PageStatePersisterproperty 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, PageAdapteris 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 PageState Persisters provided by the ASP.NET FCL (Framework Class Library).

  • HidenFieldPageStatePersister(Default):
    It will use a hidden field such as _VIEWSTATEto keep the state in Base64encoded string.
  • SessionPageStatePersister: It is used to save the state in Sessionby 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 PageStatePersisterType. It has two abstractmethods, Load and Save implementation along with two staticcustom Compression/DeCompressionmethods. 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 VIEWSTATEor ControlSateare not both null. And we are using LOSFormatterfor 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 RegisterHiddenFieldmethod 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 loadmethod 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 savemethod. First, we are decoding state information from Base64to 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 GZipCompressorclass. 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 privatemember of our newly created State Persister class and returning it in PageStatePersisterinstead of default PageStatePersisteri.e. HiddenFieldPageStatePersister; Well we are done here. Now when you will view your page in browser, you can see a hidden field name _VSTATEcontaining the state information. But you will probably notice that old _VIEWSTATEhidden 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 _VIEWSTATEfield.

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

Here is the writemethod that I used to get rid of standard _VIEWSTATEfield.

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 _VSTATEexists with compressed Base64encoded string.

Points of Interest

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

Now, I am trying to find out how much this solution is promising for me to utilize in large VIEWSTATEcase 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

You may also be interested in...

Comments and Discussions

 
SuggestionDatabase / Cache instead of Compression Pin
hAshishNangla25-Jul-11 8:34
memberhAshishNangla25-Jul-11 8:34 
GeneralWrong Regular Expression Pin
jojokim19-Oct-10 10:38
memberjojokim19-Oct-10 10:38 
GeneralRe: Wrong Regular Expression Pin
MShoab19-Oct-10 22:06
memberMShoab19-Oct-10 22:06 
QuestionDoes this work with an AJAX enabled Page? Pin
WhiteKnight19-Oct-10 10:25
memberWhiteKnight19-Oct-10 10:25 
Does not seem too!

Thanks
Peter J. Santiago
White Knight Consulting, Inc.
www.whiteknightinc.com

AnswerRe: Does this work with an AJAX enabled Page? Pin
MShoab19-Oct-10 21:29
memberMShoab19-Oct-10 21:29 
GeneralRe: Does this work with an AJAX enabled Page? Pin
WhiteKnight20-Oct-10 4:36
memberWhiteKnight20-Oct-10 4:36 
GeneralRe: Does this work with an AJAX enabled Page? Pin
MShoab20-Oct-10 5:15
memberMShoab20-Oct-10 5:15 
GeneralRe: Does this work with an AJAX enabled Page? Pin
WhiteKnight20-Oct-10 5:33
memberWhiteKnight20-Oct-10 5:33 
GeneralRe: Does this work with an AJAX enabled Page? Pin
Muhammad Shoaib Raja20-Oct-10 6:01
memberMuhammad Shoaib Raja20-Oct-10 6:01 
GeneralRe: Does this work with an AJAX enabled Page? Pin
WhiteKnight20-Oct-10 7:02
memberWhiteKnight20-Oct-10 7:02 
GeneralRe: Does this work with an AJAX enabled Page? Pin
Muhammad Shoaib Raja21-Oct-10 3:52
memberMuhammad Shoaib Raja21-Oct-10 3:52 
GeneralRe: Does this work with an AJAX enabled Page? Pin
jim lahey22-Oct-10 4:37
memberjim lahey22-Oct-10 4:37 
GeneralRe: Does this work with an AJAX enabled Page? Pin
Muhammad Shoaib Raja26-Oct-10 19:25
memberMuhammad Shoaib Raja26-Oct-10 19:25 
GeneralCode is uploaded!!! Pin
MShoab19-Oct-10 4:40
memberMShoab19-Oct-10 4:40 
GeneralSorry Code could not uploaded properly Pin
MShoab18-Oct-10 18:43
memberMShoab18-Oct-10 18:43 

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 | Terms of Use | Mobile
Web03 | 2.8.150804.4 | Last Updated 19 Oct 2010
Article Copyright 2010 by Muhammad Shoaib Raja
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid