Programmin Tool
Programmin Tool

Reputation: 6527

ASP.Net ViewState Compression: Should I bother?

So basicaly I am working on a site that is attempting to be optimized for phones (This includes pretty much any browser enabled phone) Due to the nature of the site, I want it to load as quickly as possible. At this point, I think the page is around 30k or so in size.

Now I am using viewstate, mostly for things like datagrids and not "saving" any fields to it myself.

I've seen a lot of examples like this (I swear not my blog) with 2.0 in mind , but nothing dealing with 3.5 which makes me wonder if nothing has changed since then or compressing the viewstate has fallen out of favor.

Question is, should I bother trying to compress the viewstate or is there a better solution?

Upvotes: 2

Views: 4118

Answers (5)

vasant
vasant

Reputation: 21

Compressing and Decompressing Data in Memory

First of all, we need a way to compress and decompress an array of bytes in memory. I put together this simple static class that exposes two methods: Compress and Decompress. The two available classes, GZipStream and DeflateStream, according to MSDN, use the same algorithm, so it's irrelevant which one you choose.

The code below is really simple, and doesn't need further explanation:



    using System.IO;
    using System.IO.Compression;

    public static class Compressor {

      public static byte[] Compress(byte[] data) {
        MemoryStream output = new MemoryStream();
        GZipStream gzip = new GZipStream(output, 
                          CompressionMode.Compress, true);
        gzip.Write(data, 0, data.Length);
        gzip.Close();
        return output.ToArray();
      }

      public static byte[] Decompress(byte[] data) {
        MemoryStream input = new MemoryStream();
        input.Write(data, 0, data.Length);
        input.Position = 0;
        GZipStream gzip = new GZipStream(input, 
                          CompressionMode.Decompress, true);
        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);
        }
        gzip.Close();
        return output.ToArray();
      }
    }

You need to save this class in a .cs file and put it in the App_Code directory of your ASP.NET application, making sure it's contained in the proper custom namespace (if you don't specify any namespace, the class will be available in the built-in ASP namespace).

Compressing the ViewState

Now, we can actually compress the ViewState of the page. To do that, we have to override the two methods LoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium. The code simply uses an additional hidden field, __VSTATE, to store the compressed ViewState. As you can see, by viewing the HTML of the page, the __VIEWSTATE field is empty, while our __VSTATE field contains the compressed ViewState, encoded in Base64. Let's see the code.



    public partial class MyPage : System.Web.UI.Page {

      protected override object LoadPageStateFromPersistenceMedium() {
        string viewState = Request.Form["__VSTATE"];
        byte[] bytes = Convert.FromBase64String(viewState);
        bytes = Compressor.Decompress(bytes);
        LosFormatter formatter = new LosFormatter();
        return formatter.Deserialize(Convert.ToBase64String(bytes));
      }

      protected override void SavePageStateToPersistenceMedium(object viewState) {
        LosFormatter formatter = new LosFormatter();
        StringWriter writer = new StringWriter();
        formatter.Serialize(writer, viewState);
        string viewStateString = writer.ToString();
        byte[] bytes = Convert.FromBase64String(viewStateString);
        bytes = Compressor.Compress(bytes);
        ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
      }

      // The rest of your code here...

    }

In the first method, we just decode from Base64, decompress and deserialize the content of the __VSTATE, and return it to the runtime. In the second method, we perform the opposite operation: serialize, compress, and encode in Base64. The Base64 string is then saved into the __VSTATE hidden field. The LosFormatter object performs the serialization and deserialization tasks.

You may also want to create a new class, for example, CompressedPage, inheriting from System.Web.UI.Page, in which you override the two methods and then inherit your page from that class, for example MyPage : CompressedPage. Just remember that .NET has only single inheritance, and by following this way, you "spend" your only inheritance chance to use the ViewState compression. On the other hand, overriding the two methods in every class is a waste of time, so you have to choose the way that best fits your needs.

The above was first published by Dario Solera on codeproject. http://www.codeproject.com/Articles/14733/ViewState-Compression

Upvotes: 2

Ashish Nangla
Ashish Nangla

Reputation: 31

Compression of the viewstate can only reduce it by 50% or so. I went a few steps ahead and used ViewState Substitution technique where the ViewState is replaced by a GUID on the Page. The actual ViewState data is saved in a database on the server itself, what the client (browser) gets and submits is just a 62byte token. It reduced by 200-300KB large ViewStates to 62 bytes.

Here I have written how to do this with code.. http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/

Upvotes: 0

Joel Coehoorn
Joel Coehoorn

Reputation: 415600

I am using viewstate, mostly for things like datagrids and not "saving" any fields to it myself.

It's the grids that I worry about most. Fields you save there yourself tend to be simple variables like database IDs or user names. Those won't cause as many problems, because they're small. Whole grids could potentially be a lot of data, and that's where you run into trouble.

Remember, the user has to upload the contents of viewstate from the browser to the server and then download them back on every postback. If you have a 100Mbit connection to the web server — like with a corporate lan where webforms tends to be more popular — then viewstate is great. But with cell phone browsers many users may be on the equivalent of dial-up, or even worse: paying by the byte. In this scenario, I'd try to work with it turned off as much as possible, and only enable it when necessary.

Upvotes: 4

JoshBerke
JoshBerke

Reputation: 67068

I don't think it has fallen out of favor just that saving the view state in 2.0 should work the same as saving it in 3.5. The best way to reduce viewstate is not to use it, but this is not always feasible.

In those cases you should experiment the tradeoff of bandwidth vs the extra processing time that will be required on the server. The only way to know if its worth it is to do it and measure the impact.

Edit

Another option I have seen is to save the view state on the server. It could be saved in memory, a database or disk. Depending on your environmental requirements. This would be the greatest savings on bandwidth.

Here's a code project article
Looks like a good article

Upvotes: 1

ka3751
ka3751

Reputation: 51

Having ViewState is contrary to having a fast loading web page. Why do you need ViewState? Reconsider your design and use as little as possible. I would put the burder of Session data on the server and/or database until there is a reason to keep some data in ViewState.

Upvotes: 0

Related Questions