Jeff posted about 9K worth of view state from an aspx page. Quite rightly described as "Uhhhhhhhhhhggggggggggggggggg!"
I am not going to extol the benefits of view state other than to summarize it as the price one pays to create the illusion of a stateful programming model in a stateless environment. Instead, I am going to talk of what's coming in Whidbey.
Couple of things to keep in mind: Turn off view state when its not needed and secondly ask yourself if its cheaper to requery the database or cache the queried data and data-bind on each request instead of using view state (data controls by their very nature generate significant view state).
Some controls however would be fundamentally broken when view state is turned off, and require careful programming by page developers. In Whidbey, we introduced a new concept, "Control State," that represents the minimal and essential state of a control. For example, SelectedIndex in a ListBox is an essential bit of information. You could re-databind the ListBox each request if fetching the data is cheap, but you would loose the selection state without state management. Control state allows a control to intelligently split their state into what is absolutely required and what is not. Control state is an opt-in model, so controls such as Literals don't contribute to view state simply by their existence. The idea is that control state should not get too large. Note that it cannot be turned off like view state. The intent is to allow the developer to turn off view state, but allow their pages to continue working.
The next thing I wanted to point out are the serialization improvements in Whidbey. For some time, we debated turning off view state by default; My own opinion was that we didn't need to make that drastic a change. View state (and control state) serialization now uses a new mechanism implemented in ObjectStateFormatter instead of using LosFormatter (the latter still available for compatibility reasons). Looking at my now rather ancient checkin mail, the new serializer serializes the same object graph into roughly half the size, and spends about half as much time in the serialization and deserialization process. What changed?
No more text: LosFormatter wrote to a TextWriter; ObjectStateFormatter writes to a BinaryWriter. This by itself doesn't do much, other than it enables a some other improvements.
Token-based approach: LosFormatter wrote out strings to represent data types and embedded the data within <, > brackets. None of that anymore. ObjectStateFormatter capitalizes on the underlying binary model, and writes out a byte representing the following data, and then the data.
No more strings: The old formatter converted everything to strings (numbers, booleans etc.) to write into the TextWriter. The new one writes out bytes. This saves the cost of converting to and from a string.
More compact storage: Integers are stored as 7-bit encoded numbers. So most of them (values 0 - 255) just take a single byte instead of 4. In the case of booleans, there are simply two boolean-type tokens: a true one and a false one, so there is no additional cost to storing boolean data. DateTime is also special cased. Just the TickCount is saved, which by the way isn't lossy as the string version is.
Indexing of strings: Lets say you had a DataGrid with a 100 cells. You'd have the word "Text" in view state a 100 times! This came from the Text property of TableCell. The StateBag type (that is used for ViewState) now saves property names using IndexedString. The ObjectStateFormatter special cases this type (like Pair and Triplet) to build a running table of strings. Each time a string is reused, it simply saves out a token referring to an IndexedString, and the index within this running table.
For control developers...
First look at control state, and use it judiciously. Think about your control's scenarios, and how it should work with view state disabled. Think about the state you absolutely need to carry around, and place that into control state in as compact a form as you can use.
Also, always package state information using the types special cased and optimized by the serializer (which primitive types, String, DateTime, Color, Pair, Triplet, IndexedString, arrays, ArrayLists, Hashtables, HybridDictionaries of these types). If the type isn't optimized, ObjectStateFormatter tries to find a TypeConverter that can convert to/from a string, but I would advise staying away from this. This is because it needs to store not only the converted string, but also the full (and long) assembly-qualified type name to be able to use the appropriate type converter during deserialization. The way to handle complex types is to break their state into simpler bits typically using Pair, Triplet or object arrays. The same requirement of storing type information also applies to enumeration values. If you know before hand that you are going to save an enumeration into view state in the mainline case for your control, save it as an integer and cast it to/from the enumeration type in your property accessors.
By the way, this same serializer is used for saving personalization information for Web Parts. So the same rules apply to it.
Posted on Sunday, 6/27/2004 @ 9:58 PM
| #
ASP.NET