Deal With View State Issues

Learn to face and solve your view state troubles.

Dino Esposito

October 30, 2009

11 Min Read
ITPro Today logo in a gray background | ITPro Today

CoreCoder

ASP.NET VERSIONS:1.0 | 1.1

LANGUAGES: C#

 

Deal WithView State Issues

Learnto face and solve your view state troubles.

 

By DinoEsposito

 

The viewstate is the heart of the ASP.NET built-in system that enables server controlsto persist some properties across page roundtrips. Implemented as a dictionaryof name/value pairs, the view state of all controls that form a page is firstflushed to a single hierarchical structure and then serialized to an array ofbytes. At the end of the process, the view state is stuffed into a hidden fieldand carried back and forth to the client. The view state is always managed onthe server, courtesy of the HTTP pipeline that makes a Web request become plainHTML text.

 

The viewstate is a powerful but potentially delicate feature of ASP.NET. It is powerfulbecause it enables stateful programming over a stateless protocol such as HTTP.The view state is the container that pages use to preserve their state. Whenthe page posts back, the page framework deserializes the view state - if theview state is present - and sets up a runtime environment that recreates thesame situation of the time in which the page was initially sent to the browser.Each involved control saves its critical state into the view state and the pageframework restores it when processing the page back. The state information,properly encoded, goes to the client, but is not used by the browser or theclient-side environment. The view state represents the context of the call asprepared and served by the ASP.NET page framework. Page authors can control,both in quantity and quality, the data stored in the view state and aneffective management of the view state can mark the difference between a goodand a poor application design. If, for any reasons, the view state is alteredalong the way an error occurs. Furthermore, a too large view state can easilyslow down the page.

 

Watch Your View State Types

Bear inmind that not all data types that an ASP.NET application is enabled to use canbe saved to the view state. For example, a data type that is not serializablecannot be persisted in the view state. However, non-serializable types forwhich you define a type converter class can be stored in the view state. A typeconverter is a class that performs two-way conversion between the value of acustom type and plain text. The type converter class has the capability ofrendering the contents of a custom type as text to the user. In addition, thetype converter can rebuild a valid instance of that type based on a properlyformatted string of text. In summary, any data types you plan to store in theview state must either be serializable or supply a type converter class.Notice, though, that types that are serializable but lack a type converter areslower to serialize and generate a much larger output than those based on atype converter.

 

Forperformance reasons, and to generate a more compact array of bytes, you shouldensure that the view state contains only simple types or types that provide atype converter. (Basically, the type converter transforms a "complex" type in asimple, text-based representation.) Note that a TypeConverter for a type isimplemented outside the type itself and is associated with it by applying aTypeConverterAttribute attribute:

 

[TypeConverter(typeof(YourClassConverter))]

public classYourClass {

   :

}

 

In theprevious code snippet the converter class is YourClassConverter bound to theYourClass type using the TypeConverter attribute. On a side note, consider thatthe type converter object has a double use. Not just the ASP.NET frameworkemploys it at runtime during the view state serialization, but also at designtime to provide properties of that type with an appropriate representation inthe property grid.

 

What isthe main reason for limiting the use of certain types - both user-definedclasses and the majority of the classes in the .NET Framework - when it comesto storing data to the view state? The magic word is optimization.

 

The LOS Formatter

Both tominimize the size of the hidden field and to generate the output faster, theASP.NET page framework serializes the view state using an internalserialization format that is optimized for primitive types, and for String,ArrayList, and HashTable types. This format is known as the Limited ObjectSerialization (LOS).

 

LOS isdesigned for obtaining the maximum compression of a limited number of datatypes. Classes that implement the LOS algorithm are not completely public andfully documented because (as of ASP.NET 1.1) LOS is considered a featureinternal to the ASP.NET framework. LOS is not designed to be a general-purposeserialization mechanism, but simply a format optimized for persisting some dataacross Web requests. The schema of the LOS format is subject to change asfuture versions of ASP.NET see the light.

 

The ideabehind the LOS format is based on a few known facts. The most common data typesthat people need to persist are strings, arrays, and hashtables. Furthermore,hashtables and arrays are likely to contain null or repeated entries. Finally,there are a set of common types (Int32, Boolean, Color, Unit) that would makeup almost the whole of the non-string and non-collection data.

 

For allof these types the LOS formatter is at its best. If you store a different type,the formatter first attempts to find a type converter so that the data ispersisted as a string. If no type converter exists, the default binaryserialization is used. In terms of raw performance and the space occupation,the binary serialization is significantly worse than the LOS formatter.

 

Eachcontrol, including the Page class, has its own view state. The view state isimplemented as an instance of the StateBag class, a dictionary class with a fewcustomized members. The view state of the page is serialized a moment beforethe page is rendered to HTML. When this happens, the ViewState property of allconstituent controls is flushed into an all-encompassing structure, which isthen serialized to an array of bytes using the LOS formatter. The view stateinformation is stored using a hashtable indexed by control name in which eachentry contains a hashtable of children and data. Next, the array of bytes isBase64 encoded and flushed into a hidden field in the page that goes to thebrowser. In no case does the view state get encrypted.

 

Optimizingpages and controls that make an intensive use of the view state is a delicateart. The best two practices for view state fine tuning are summarized in thesection "Customize the View State Management" toward the end of this article.

 

Fend Off View State Corruption

Whenyour application raises a view state error, chances are that the error messagehas to do with a "presumed" corruption of the stored data. What the ASP.NETframework reports as a corruption is simply the system's inability to restorethe posted view state. As mentioned, the view state is stuffed into a hiddenfield named __VIEWSTATE appended to the page served to the browser. When thepage posts back, the hidden field is part of the posted values. The frameworklooks up for a __VIEWSTATE field and reads its Base64 encoded text. Afterdecoding the text, the page passes it to the LoadViewState method of pageconstituent controls, giving each a chance to extract any pertinentinformation.

 

Beforethe process starts, though, the ASP.NET framework performs a security check onthe view state returned from the client. If the EnableViewStateMac pagedirective is enabled (yes by default), the view state serializer calculates ahash value on the array of bytes resulting from the LOS serialization. This20-byte hash value is appended to the array.

 

When theuser works with the page on the client, the view state is there stored in ahidden field, but potentially exposed to any sort of manipulation. Attackerscould dissect the view state and insert anything new - from malicious scriptcode to inconsistent values. Particularly at risk are server controls thatdon't HTML-encode their output, such as DataGrid, DataList, and Label to namejust a few.

 

Theappended hash value guarantees that the view state has not been tampered with.Can an attacker modify the hash value too? While this can't be excluded, it israther a remote possibility. Let's see why. The hash value is calculated usingthe Secure Hash Algorithm 1 (SHA1) algorithm or any hash or encryptionalgorithm of choice. The SHA1 algorithm produces a larger hash size than otheralgorithms such as Message Digest 5 (MD5) and is considered more secure. Thehash algorithms don't work on the view state contents alone. The source isenriched by other information such as the validation key, the class name of thepage, its source path, plus - in ASP.NET 1.1 only - any custom string that theuser places in the ViewStateUserKey property of the Page class. To be able tocorrupt the view state, an attacker must know this information too. Inparticular, the validation key is generated at setup time and stored in theLocal Security Authority (LSA) area. This is difficult information for anattacker to crack.

 

Youshould note that view state protected with SHA1 or MD5 can be decoded intransit or on the client side and can potentially be viewed in plain text. Toavoid this, you might want to opt for a slower approach based on a trueencryption algorithm such as the 3 Data Encryption Standard (3DES). Using 3DESyou can detect changes in the view state and to also encrypt it while intransit, adding confidentiality to the data. When in this state, even if viewstate is decoded, it cannot be viewed in plain text.

 

What'sthe role of the EnableViewStateMac attribute? If set to true, the hash value(known as the message authentication code) is recalculated and compared to thatappended to the view state. If the two don't match, the framework concludesthat the view state has been corrupted and throws an exception.

 

A simpledebugging tip is, set the EnableViewStateMac attribute to false and re-run thepage. Yours is not a security problem if the error persists. If the page runsjust fine, you have reasons to be concerned about security; something happenedto modify the page under your user's nose.

 

Dealing With Long View States

So theview state is packed and persisted as a hidden field. However, the view stateof real-world pages can easily reach the remarkable size of 10KB or so. Anotherfrequent reason that may lead to invalid view state exceptions is that theunderlying browser is not capable of carrying all those bytes back and forth.As a result, the contents of the view state is truncated. This is particularlylikely to happen on pretty simple Web browsers such as WebTVs and PDAs. How doyou work around this issue? And just how did the ASP.NET team solve the sameissue in ASP.NET mobile controls?

 

The viewstate is saved to a hidden field only by default; you can decide to persist itelsewhere. The view state of ASP.NET mobile controls is left on the serverstored in Session. The same route can be taken here to support browsers thatcannot handle such large hidden fields and resulting requests. In Figure 1 youcan see how to proceed overriding a couple of methods. Figure 2 shows thesample page with no view state bundled.

 

<%@language="C#" %>

 

protectedoverride object

 LoadPageStateFromPersistenceMedium()

{

  return Session["_ViewState"];

}

protectedoverride void

 SavePageStateToPersistenceMedium(objectviewState)

{

  Session["_ViewState"] = viewState;

}

 

Figure1. To change theway in which the view state is stored you must simply override the methodLoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium.

 


Figure 2. The sample page doesn't show offview state information, although the read-only attribute of the textbox is justa piece of information that normally goes to the view state.

 

Customize the View State Management

It'scommon knowledge that the overall size of the view state goes with the numberof controls that form the page. Not all controls, though, affect the size ofthe view state in the same manner. The amount of data that a TextBox controlplaces in the view state pales compared to say, what a DataGrid persists. Eachcontrol exposes its own view state through the ViewState property and uses thisdictionary to persist critical data across roundtrips. The programmer, though,can exercise some control over the quantity of data that server componentsstore in the view state. This can be accomplished in either of two ways. First,the programmer can disable the view state for all controls in a page or for aspecific control. If you're going to implement such a feature, you shoulddouble check your code to ensure that no unpleasant side effects sneak intoyour application. In fact, disabling the view state of a control can certainlyimprove performance, but can hinder the functionality of the component acrossroundtrips because of properties that do not retain their last set value.

 

You canalso control the way in which a data type is stored in the view state. Thispossibility comes in handy especially when you deal with a custom type thatotherwise cannot be stored in the view state. The base class Control providestwo overridable methods for you to control the view state serialization anddeserialization process for the control. The methods are SaveViewState andLoadViewState:

 

protectedvirtual object SaveViewState();

protectedvirtual void LoadViewState(object savedState);

 

You haveto override them in pairs. SaveViewState creates and returns a data structurethat contains the information to save. LoadViewState receives the samestructure as packed by SaveViewState, extracts the data, and populates theinternal members.

 

DinoEsposito is atrainer and consultant who specializes in ASP.NET, ADO.NET, and XML. Author of Programming Microsoft ASP.NET and Building Web Solutions withASP.NET and ADO.NET(both from Microsoft Press), Dino is also the cofounder of http://www.VB2TheMax.com. Write to him at mailto:[email protected].

 

 

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like