ViewState: All You Wanted to Know
page 1 of 1
Published: 17 Oct 2003
Unedited - Community Contributed
Abstract
This article looks at what ViewState is NOT and what it is, as well as exploring the internal format of ViewState and how you can parse it yourself.
by Paul Wilson
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 140114/ 235

ViewState: All You Wanted to Know

ViewState: All You Wanted to Know

Paul Wilson
www.WilsonDotNet.com
www.ASPAlliance.com/PaulWilson

Previous Article            Page Events and PostBack            Next Article

What ViewState is Not

First, lets consider what ViewState is NOT, since there are several common misconceptions. ViewState does not help restore posted values to form controls, although this is said at times. The easiest way to see this is to disable a control’s ViewState and watch its value be restored. This is done automatically for us by matching the posted form variable name with the control, although this only works for controls that are created by the time the Load event is completed. So while ASP.NET does automate the restoring of form values, this is not part of ViewState.

ViewState also does not auto-recreate any controls that were dynamically created in the code. This is actually something that many of us have discovered the hard way, since it doesn’t work. Any controls that you dynamically create in your code must therefore be recreated in the code. This can be a little difficult at times to work around, especially for controls created in events, but it is doable if you keep track of what’s been previously done and recreate it on each Load. ViewState can, however, be used to track this information, but we must manually code for it.

Finally, ViewState is not intended for user or session data, nor for transferring across pages. ViewState is only designed for state data related to the current page and its various controls. It does not get sent to a new page in any case, not through links, redirects, or server transfers. There may be things that you want to access on multiple pages, due to redirects or transfers, but the solutions involve using either cookies, session, or the request context, not ViewState. We will also see that ViewState is neither secure, nor always the best use of server resources.

So What is ViewState

ViewState is used to track and restore the state values of controls that would otherwise be lost, either because those values do not post with the form or because they are not in the page html. This means that a control totally defined in your page html, with no changes made in the code, will have no ViewState at all, as is often the case when using drag-n-drop with static content. Instead, ViewState only holds the values of properties that are dynamically changed somehow, usually in code, data-binding, or user interactions, so that they can be restored on each request.

So, ViewState holds properties you change in code, any data that you bind to a control in code, and any changes that occur as a result of user interactions that were triggered with a PostBack. An example of a user interaction is a user selecting a date or moving a month in the calendar, which triggers a PostBack that changes properties of the calendar to match the user’s request. The new date selected or month being viewed must be persisted in the calendar’s ViewState since these are properties that will need to be restored but which will not be posted next time.

ViewState also provides a StateBag, which is a special collection or dictionary, for each page that you can use to store any object or value, associated with a key, to retain across PostBacks. This is useful for your own custom items that are relevant to only that specific page instance, since these values will automatically post with that page, but not transfer to any other pages. One very good use of custom ViewState is to keep track of any dynamically created controls, which you can then manually recreate on each post based on your tracking data in ViewState.

And What is the Format

ViewState is by default serialized and passed across page PostBacks as a hidden form field, __VIEWSTATE, that is Base64 encoded so that it is not easily readable, but not encrypted. ViewState is by default tamper-proof, however, since a hash is applied based on machine key, although this is disabled by setting the enableViewStateMac property to false (see Listing 1). ViewState can be optionally encrypted, by setting up machineKey validation (see Listing 2), but this must be done at the machine level and it uses more resources so its not recommended.

ViewState is saved before rendering in the Page.SavePageStateToPersistenceMedium method and it is restored on PostBacks in the Page.LoadPageStateFromPersistenceMedium method. Both of these methods can be easily overridden to save ViewState to Session (see Listing 3), which is useful for low-bandwidth cases, like Mobile devices which use Session by default. Storing the ViewState in other data stores, like a database or even advanced Session modes, requires serialization and deserialization using the special LosFormatter class (see Listing 4).

Finally, lets take a look at the internal format of the ViewState object for completeness sake. Each control’s ViewState is stored in a Triplet (System.Web.UI.Triplet) with the First object being a Pair (System.Web.UI.Pair), or Array or Pairs, of ArrayLists of related name-values. The Second object of the Triplet is an ArrayList of that control’s child indices in control tree, and the Third object is an ArrayList of the similar associated Triplets of those child controls. Its all rather hard to describe, so look at the example and try it for yourself (see Listings 5/6).

Listing 1: ViewState Machine Hash Disabled
machine.config or web.config: <pages enableViewStateMac='false' />
page level directive:         <%@Page enableViewStateMac='false' %>
page level script code:       Page.EnableViewStateMac = false;
Listing 2: ViewState Encryption is Enabled
machine.config: <machineKey validation='3DES' validationKey='*' />
where the validationKey must be the same across a web-farm setup
also requires the enableViewStateMac property setting to be true
Listing 3: ViewState Saved in Session State
protected override object LoadPageStateFromPersistenceMedium() {
 return Session["ViewState"];
}
protected override void SavePageStateToPersistenceMedium(object viewState) {
 Session["ViewState"] = viewState; 
 // Bug requires Hidden Form Field __VIEWSTATE
 RegisterHiddenField("__VIEWSTATE", "");
}
Listing 4: ViewState Saved in Custom Store
protected override object LoadPageStateFromPersistenceMedium() {
 LosFormatter format = new LosFormatter();
 return format.Deserialize(YourDataStore["ViewState"]);
}
protected override void SavePageStateToPersistenceMedium(object viewState) {
 LosFormatter format = new LosFormatter();
 StringWriter writer = new StringWriter();
 format.Serialize(writer, viewState);
 YourDataStore["ViewState"] = writer.ToString();
}
Listing 5: ViewState Decode/Parse Example
Encoded ViewState:
dDwxMjM0NTY3ODkwO3Q8cDxsPHBycEE7cHJwQjtwcnBDOz47bDx2YWxBO3ZhbEI7dmFsQzs+PjtsPGk8
MD47aTwyPjtpPDM+O2k8NT47PjtsPHQ8cDxsPHBycEE7cHJwQjs+O2w8dmFsQTt2YWxCOz4+Ozs+O3Q8
cDxsPHBycEE7cHJwQjs+O2w8dmFsQTt2YWxCOz4+Ozs+O3Q8cDxsPHBycEE7cHJwQjs+O2w8dmFsQTt2
YWxCOz4+Ozs+O3Q8cDxsPHBycEE7cHJwQjs+O2w8dmFsQTt2YWxCOz4+Ozs+Oz4+Oz4=
Decoded ViewState:
t<1234567890;t<p<l<prpA;prpB;prpC;>;l<valA;valB;valC;>>;
l<i<0>;i<2>;i<3>;i<5>;>;l<
t<p<l<prpA;prpB;>;l<valA;valB;>>;;>;
t<p<l<prpA;prpB;>;l<valA;valB;>>;;>;
t<p<l<prpA;prpB;>;l<valA;valB;>>;;>;
t<p<l<prpA;prpB;>;l<valA;valB;>>;;>;>>;>
Parsed ViewState:
t<1234567890;             Page-Level Triplet is Special Case
  t<p<l<prpA;prpB;prpC;>; Triplet-First:Pair-First:ArrayList
      l<valA;valB;valC;>                Pair-Second:ArrayList
     >;
    l<i<0>;               Triplet-Second:ArrayList:Indices
      i<2>;                                        of the
      i<3>;                                        Children
      i<5>;                                        Controls
     >;
    l<t<p<l<prpA;prpB;>;  Triplet-Third:ArrayList:Triplets
          l<valA;valB;>                           of the
         >;                                       Children
       ;                                          Controls
       >;
      t<p<l<prpA;prpB;>;  Each Sub-Triplet follows same Pattern
          l<valA;valB;>   
         >;
       ;                  More Levels Possible if sub-Children
       >;
      t<p<l<prpA;prpB;>;  Each Sub-Triplet follows same Pattern
          l<valA;valB;>
         >;
       ;                  More Levels Possible if sub-Children
       >;
      t<p<l<prpA;prpB;>;  Each Sub-Triplet follows same Pattern
          l<valA;valB;>
         >;
       ;                  More Levels Possible if sub-Children
       >;
     >
   >;                     Closing of Special Page-Level Triplet
 >
Listing 6: ViewState Decode/Parse Code
protected override void SavePageStateToPersistenceMedium(object viewState) {
 // Call Base Method to Not Change Normal Process
 base.SavePageStateToPersistenceMedium(viewState);
 // Retrieve ViewState and Write Out to Page
 LosFormatter format = new LosFormatter();
 StringWriter writer = new StringWriter();
 format.Serialize(writer, viewState);
 string vsRaw = writer.ToString();
 Response.Write("ViewState Raw: " + Server.HtmlEncode(vsRaw));
 // Decode ViewState and Write Out to Page
 byte[] buffer = Convert.FromBase64String(vsRaw);
 string vsText = Encoding.ASCII.GetString(buffer);
 Response.Write("ViewState Text: " + Server.HtmlEncode(vsText));
 // Parse ViewState -- Turn On Page Tracing
 ParseViewState(viewState, 0);
}
private void ParseViewState(object vs, int level) {
 if (vs == null) {
  Trace.Warn(level.ToString(), Spaces(level) + "null");
 }
 else if (vs.GetType() == typeof(System.Web.UI.Triplet)) {
  Trace.Warn(level.ToString(), Spaces(level) + "Triplet");
  ParseViewState((Triplet) vs, level);
 }
 else if (vs.GetType() == typeof(System.Web.UI.Pair)) {
  Trace.Warn(level.ToString(), Spaces(level) + "Pair");
  ParseViewState((Pair) vs, level);
 }
 else if (vs.GetType() == typeof(System.Collections.ArrayList)) {
  Trace.Warn(level.ToString(), Spaces(level) + "ArrayList");
  ParseViewState((IEnumerable) vs, level);
 }
 else if (vs.GetType().IsArray) {
  Trace.Warn(level.ToString(), Spaces(level) + "Array");
  ParseViewState((IEnumerable) vs, level);
 }
 else if (vs.GetType() == typeof(System.String)) {
  Trace.Warn(level.ToString(), Spaces(level) + "'" + vs.ToString() + "'");
 }
 else if (vs.GetType().IsPrimitive) {
  Trace.Warn(level.ToString(), Spaces(level) + vs.ToString());
 }
 else {
  Trace.Warn(level.ToString(), Spaces(level) + vs.GetType().ToString());
 }
}
private void ParseViewState(Triplet vs, int level) {
 ParseViewState(vs.First, level + 1);
 ParseViewState(vs.Second, level + 1);
 ParseViewState(vs.Third, level + 1);
}
private void ParseViewState(Pair vs, int level) {
 ParseViewState(vs.First, level + 1);
 ParseViewState(vs.Second, level + 1);
}
private void ParseViewState(IEnumerable vs, int level) {
 foreach (object item in vs) {
  ParseViewState(item, level + 1);
 }
}
private string Spaces(int count) {
 string spaces = "";
 for (int index = 0; index < count; index++) {
  spaces += "   ";
 }
 return spaces;
}

Author Bio

Paul Wilson is a software architect in Atlanta, currently with PRG-Schultz. He specializes in Microsoft technologies, including .NET, C#, ASP, SQL, COM+, and VB. His WilsonWebForm Control allows Multiple Forms and Non-PostBack Forms in ASP.NET. He is a Microsoft MVP in ASP.NET and is also recognized as an ASPInsider. He is a moderator on Microsoft's ASP.NET Forums, as well as one of the top posters. He is holds the MCSD, MCAD, MCDBA, and MCSE certifications. Please visit his website, www.WilsonDotNet.com, or email him at Paul@WilsonDotNet.com.


User Comments

Title: Developer   
Name: ali
Date: 10/20/2010 4:51:15 AM
Comment:
thanx... good article ..
so much helpful
Title: Sr. Developer   
Name: Sravan
Date: 7/9/2010 9:45:05 AM
Comment:
wow, what a complete and informative article. its wonderful and easy to understand. thanks for the article.
Title: Landsailor   
Name: Pete Lyons
Date: 8/31/2009 8:16:02 PM
Comment:
Whoa! My head is spinning... This article was amazing - Thanks Paul!

~Pete
Title: Developer   
Name: Khyati Shah
Date: 5/21/2008 2:06:22 AM
Comment:
Thanks,
you have cleared my fundamentals. I was facing a situation where a build was working locally but was not working on a cluster. The exception was caused due to mismatching validateKeys for which i added the key in the machineKey.config. But after reading this article i think it may not be the best solution to do that, since it has its over head.
Title: Developer   
Name: Sam Jackson
Date: 5/13/2008 1:14:26 PM
Comment:
How is the object viewState being populated in the SavePageStateToPersistenceMedium method? What sets the object? Do you have a complete example of this? There seems to be a step missing?
Title: viewstate vs session   
Name: DaveM
Date: 1/18/2008 5:52:16 PM
Comment:
Nice article! I am trying to find the correct way to save state for an ajax tabpage which includes a usercontrol and a button to add a second tab with a new copy of the usercontrol. Upon postback the changes are lost in the first tab's usercontrol. I have played around with viewstate but have not had success in this yet. You mention that viewstate may not be the correct way to save dynamically created controls and that you might prefer session variables. Do you have any suggestions or code examples? I am in a asp.net 2.0 environment. dmohr@asainc.net Thx Dave
Title: A common unanswered Questions   
Name: Deepak
Date: 9/23/2007 9:14:27 AM
Comment:
A common question I come across is "Can I pass viewstate between pages?" and the answer on all pages is NO.
BUT,
Say I have Page1 having a button. On click of button I can get the value of __viewstate hidden field, append it in querystring and pas it on to another page. There I can decode it and use the information. OR ELSE I can do a postback to another page, get the Viewstate data using request.form and again decode it, then why do people say viewstate can not be transfered between pages?????
Title: Good Article   
Name: Ravi
Date: 1/29/2007 5:55:09 AM
Comment:
This is good for viewState but better to give a one example
Title: Great Article   
Name: AVS Prasad
Date: 12/13/2006 1:59:05 PM
Comment:
Hi,

This is really a great article that has helped me in clearing some of the assumptions that I had about the viewstate. Thanks a lot for such a nice article.

Thanks & Regards,
Prasad.
Title: sessions value has to be dynamically uploded   
Name: krishna prasad
Date: 6/2/2006 8:51:58 AM
Comment:
how to present the session vlaue in other page and has to be changed tat value dynamically
Title: k   
Name: k
Date: 5/23/2006 2:51:22 AM
Comment:
Excellent ,but should have been much mare lengthy
Title: Very good article | Not able to help me   
Name: Kapil
Date: 12/13/2005 8:39:22 AM
Comment:
Hi,

This is a very good article and gives lot of information about view state management. But i am facing some issue view states. Somewhat related/unrelated. It would be goo if someome can provide some help. The problem is:

I have 3 user controls sitting on an ASPX page being loaded in Placeholder controls. We are loading all 3, but rendering only one based on certain conditions. The problem that we are facing is that when we post back the same use control, the server side controls maintain their view state, which messes up the data.

Any clue?

Thanks,
Kapil
Title: anything   
Name: someone
Date: 11/22/2005 12:30:40 AM
Comment:
This is the best example of a user making misuse of the feedback facility !
Title: Post to another page   
Name: mozzy
Date: 9/6/2005 9:38:08 AM
Comment:
I have found a way how to Post a form to another page rather doing a post back. however i can't send the Viewstate of the form to the second page since it would cause a validation error, hence i stored the viewstate hidden field value in another hidden field. now my question is:
is it possible to take the viewstate from the first form and merge it with the viewstate of the second form?
my idea was to decode both viewstates, discard the mac id of the first view state add it to the second viewstate encode the whole thing and then store it back as a usual viewstate.

does anybody know how to do such a thing?
Title: Re: Manipulate Viewstate using javascript   
Name: Paul Wilson
Date: 8/3/2005 7:42:23 AM
Comment:
You cannot change ViewState on the client, nor should you. The whole point is so the page can recreate what the last state on the server was -- and then compare that if necessary to what was posted back to determine changes. If you are making some more sophisticated changes than you'll need to make a design to get the information relevant back to the server.
Title: Manipulate Viewstate using javascript   
Name: K. Hari Das
Date: 8/3/2005 2:04:44 AM
Comment:
Hi Paul,

I am using Infragistic webgrid controls in my page. There are two of them between which the user can transfer records to and fro. But the problem is when I am saving this page, I am not able to get the client side changes on the server side.

I think the viewstate is not getting updated on the client side.

Do you have any idea on how to go about this. Is there a way by which I can refresh the viewstate on the client side to reflect client side changes or can I manipulate viewstate using javascript.

Thanks & Regards,

K. Hari Das, Technology Architect
(Cell No - 91-09823150049)
Info-Spectrum India Pvt. Ltd.
H.B.Hall, Sonegaon,
Nagpur - 440025
INDIA
Title: Good   
Name: Saleena
Date: 6/14/2005 2:40:47 AM
Comment:
Really a good one...for the beginners
Title: System Analyst/Developer   
Name: Greg Jackson
Date: 6/11/2005 10:53:17 AM
Comment:
This was a good article. I ran into an issue where session variables were coded in the asp.net pages. The application was tested on a single server then deployed to a load balanced environment. I started receiving data state issues and immediately assumed that view state would resolve my issue by replacing session with viewstate and server.transfer. To my dismay the solution combo I tried did not provide the stateless environment I was trying to build. Even though I have abandoned that design avenue I am still in search of another way to provide a stateless environment while at the same time not performing the overhead of recreating data I already possess in the page and that is needed between pages. This article provided the evidence that I needed to begin investigating an alternative solution.
Title: Re: Very Good Article   
Name: antibozo
Date: 6/2/2005 12:19:50 AM
Comment:
No, the t<123456890; value appears to be an identifier for the .aspx page itself--perhaps a file identifier (a la inode number) salted with the modification time. This may be a measure to limit one's ability to take a __VIEWSTATE from one page and hand it to another page which uses the same machine id, or even to replay a __VIEWSTATE from one version of a page into a later version where the controls have been reordered.

The machine id is a secret, so it can't be embedded in __VIEWSTATE.

The message authentication code (digest of __VIEWSTATE + secret) is appended to __VIEWSTATE before base64 encoding. It is 20 bytes long, which is evidence that a SHA1 digest may be used.

The example __VIEWSTATE Paul used does not have a message authentication code. If it did, you would see a bunch of binary data (20 bytes as noted above) tacked on after the last >.

It would be nice if someone would actually thoroughly document the format of this beast. Using asp.net to decode it is not particularly informative. What, for example, does @0 mean? What happens when a control contains a < or ; character?
Title: good   
Name: jagaidh
Date: 5/16/2005 9:12:23 AM
Comment:
good news for viewstate. need one examples.
Title: Viewstate Parser   
Name: Alan
Date: 4/25/2005 9:38:44 AM
Comment:
Hi

Good article and it’s been a start for me building a parser like yours but I wanted it to show name value pairs.

What a pain in the a$$ it is,

Often Triplets contain arrays that in turn have arrays and often the arrays only hold one item whilst other arrays repeat the same data twice.

On a simple page with a grid control you end up drilling down about 9 levels and then the data you can see means little or nothing.

Will send you a copy if I ever get it done

ZZZAlan@AlansHome.co.UK

Regards

Alan Britain
Title: Great   
Name: Troy
Date: 3/30/2005 1:35:32 PM
Comment:
Most useful article describing view state.
Title: Re: Very Good Article   
Name: Paul Wilson
Date: 12/21/2004 1:02:58 PM
Comment:
Thanks Adam.

Yes, as for as I can deduce, that first triple is the hash for that page that is used on postback to make sure nothing has been tampered with, but since none of this stuff is really documented its mostly an educated guess.

Thanks, Paul Wilson
Title: Very Good Article   
Name: Adam
Date: 12/21/2004 12:40:08 PM
Comment:
Great article thats really useful (and clear).

One question tho regarding the page level triplet within the decoded or parsed viewstate - in this case given as t<1234567890; - Is this the machine key thats used to hash viewstate data for form postbacks? If not are you aware what this data is (used for)?

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2014 ASPAlliance.com  |  Page Processed at 8/27/2014 2:55:57 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search