ANSWER: A while back I wrote an article for MSDN online titled Understanding ASP.NET View State, and blogged about the article in this past entry. I recently noticed a comment in that blog entry from Matthias Cavigelli, asking:
When I disable the ViewState property of the page, I still have the hidden field
__VIEWSTATE in the html code. Could you explain why it's still there although it's not enabled?
What Matthias is referring to is the
EnableViewState property, which is defined in the
System.Web.UI.Control class (which means that all ASP.NET server controls have this property, including the
Page class from which all ASP.NET Web pages are derived.) This property defaults to True, which means that, by default, a control should track its view state and save its view state during the
SaveViewState stage of the page's lifecycle. By setting
EnableViewState to false, a control is saying, "Don't bother recording my view state."
EnableViewState to False on certain state-heavy controls is a good way to trim the size of a page's view state. Of course, you must take care when tweaking this property, since the state-heavy controls typically rely on the view state to maintain their functionality. Here's a good example of when you can set
EnableViewState to False: when you have a DataGrid Web control on a page that simply displays data, and where the DataGrid's properties are not programmatically changed on postback. (Note: if this page does have postbacks you'll have to make sure to rebind the database data to your DataGrid on every postback.)
If your page does not perform any postbacks at all, having view state is a big waste. So, you might as well set the
EnableViewState to False, so that no view state is saved for the entire page. Or so you'd think. If you set
EnableViewState to False for the page, you'll still get a hidden
__VIEWSTATE form field, although it will be pretty small. Why does this hidden form field exist at all?
To answer this question it is important to realize that view state really is paramount to Web Forms, not the
Page class. (A Web Form is a server-side
<form> tag, which is represented in the .NET Framework via the
System.Web.UI.HtmlControls.HtmlForm class.) If a Web Form exists, there typically needs to be a hidden
__VIEWSTATE form field. But the Web Form does not know the complete view state of the page. The
Page class, for instance, has a
ViewState property, into which a page developer can store items into the view state. The Web Form, obviously, is ignorant about this. So there's this chicken-and-egg thing going on here - the
Page knows how to completely represent the view state, but it's the Web Form that cares about it, not the
Page. The end result is that the
Page class is responsible for generating the hidden
__VIEWSTATE form field, but it's the Web Form that knows whether or not this is needed.
To overcome this hurdle, the
Page class needs some way to know whether or not the
__VIEWSTATE form field needs to be emitted or not. To allow for this, the
Page class provides a public
RegisterViewStateHandler() method; if this method is called during the page lifecycle, a
__VIEWSTATE hidden form field will be emitted, even if the
EnableViewState property is set to False.
From a Web Form's perspective, it always needs to save view state. Well, this is the way the Web Form class was programmed by Microsoft. You can see this by examining the
protected override void OnInit(EventArgs e)
Personally, it would seem to make more sense to me to have
Page.RegisterViewStateHandler() called only if
Page.EnableViewState is true, but there may be a reason behind this that I haven't seen. Anywho, when the Web Form is rendered, it calls an additional two of the
Page class's methods:
OnFormRender() - this adds the
__VIEWSTATE hidden form field along with any registered hidden form fields or script blocks registered via
OnFormPostRender() - this adds any script blocks registered via
Page.RegisterStartupScript() and any client-side arrays registered via
You may still be wondering why when the
EnableViewState is False that the
__VIEWSTATE hidden form field has anything in it. Well, if you take a look at the
SavePageViewState() method, you'll see:
internal void SavePageViewState()
Triplet triplet1 = new Triplet();
int num1 = this.GetTypeHashCode();
triplet1.First = num1.ToString(NumberFormatInfo.InvariantInfo);
triplet1.Third = this._registeredControlsThatRequirePostBack;
triplet1.Second = base.SaveViewStateRecursive();
So what you see her is the following: if
_needToPersistViewState is False, then nothing is saved. Well, this flag is set to True when the Web Form calls
Page.RegisterViewStateHandler(). So a
Triplet is built up, with the first item containing the page's hash, the third item containing an ArrayList of Web controls that require a postback. Now, the second item is where the meat of the view state comes from - this is the sum of the view state of the controls in the page. But if
EnableViewState is False for the page,
SaveViewStateRecursive() returns null.
So even if you set the
EnableViewState to False, you'll still get a
__VIEWSTATE hidden form field with the
Page's hash and ArrayList of controls that require postback. I still don't see why this is needed, but there is likely a good reason.
In an upcoming article of mine for MSDN online, I talk more about the
Page class's methods for registering client-side elements - scripts, arrays, hidden form fields, etc. Keep your eyes peeled on the ASP.NET Dev Center!