Size of data in the ViewState

I love the ViewState.

I know it's a much-maligned technology. I know it can bloat out of all control. I know it can be an effort to tame it, but spend an afternoon reading up on it and it can really be your friend.

It can be a handy place to store all sorts of state data that you don't want to (or can't) track on the server. It's dead easy to add values to it programmatically and retrieve them after a postback.

You can serialize pretty much anything into the ViewState. Though putting an instance of your Customer class in there would blatantly be a bad idea - it would be vast once serialized - storing smaller constructs is feasible, and usually holding a few flags is sufficient to maintain the state of your page.

What can be a little surprising, though, is how big some data items are compared with others when they're serialised to the ViewState.

I spent an afternoon putting all sorts of items into the ViewState and seeing how much it made the ViewState grow. The results are in the graph below. (Click to see a legible-sized version.)

ViewState Graph

Note that all the figures are multiples of four - this is because the ViewState is base 64 encoded. Unfortunately it means the figures aren't quite spot-on to the byte, but they're good enough for our purposes.

The most important thing to notice is the long bar at the bottom. A List<string> containing only two three-letter strings took a whopping 312 bytes! Compare this with the array of strings holding the same values, which took only 24 bytes. An easy lesson: if you're putting a set of objects into the ViewState, turn that list into an array first.

In fact, arrays perform pretty well. Arrays of arrays carry a bit of overhead but aren't too bad, all things considered.

Surprisingly, int.MaxValue takes more space than the integer 1. Storing int.MaxValue.ToString() took more again, but these figures are still pretty small so it doesn't make much difference.

Converting a DateTime to a string took rather more space than the raw DateTime itself.

On the other hand, decimals take a vast amount of space for what they are (and decimal.MinValue took significantly more than decimal.One); but converting them to strings dropped the space right back down again.

I'm surprised that storing a Guid takes three times as much space as its string representation - I can't imagine what extra information is being serialized there.

Similarly, types take quite a bit of space; storing their full names is sufficient to regain the class object later and takes only about a third of the space. (Though to be fair I can't imagine what circumstances would lead you to putting a Type into the ViewState.)