Click here to Skip to main content
15,881,744 members
Articles / Web Development / ASP.NET
Article

Common Misconceptions about ASP.NET ViewState

Rate me:
Please Sign up or sign in to vote.
1.75/5 (6 votes)
20 Feb 20079 min read 43.8K   14   16
Descibes what happens Behind the Scenes for ASP.NET ViewState

Introduction


I am sure after reading this article most of issues regarding <place><placename>View <placetype>State will get cleared
out . If you disable the View State of controls, 90% of control features cannot be used.
Initializing the control at right place will fix most of the issues. I have taken inspiration for
writing this FAQ after reading David Creed article about ViewState in ASP.NET forum.Thanks to Him for writing such amazing content :). I have Converted His Ideas into
FAQ's which is easier to read and targets the problems which developers face on a daily
basis .


1) Any property value we declare in ASPX or .ascx file goes to ViewState? Is this
Statement correct?

All static Data which you assign to Server control doesn't go to <place><placename>View <placetype>State. Common
Misconception is anything typed in control's property goes to view state

For Example If i have two Label controls

<asp:Label id="label1" runat="server" Text="abc" />

one with Text="abc" and another one with Text="1234" .In both cases Viewstate Doesn't
contain Value of Text field. Same thing is true for any control. Here I am talking about
View state of Label And <place><placename>Hence <placename>View <placetype>State of Control which contains the Label.


Now if you Type the Text property of Label in Page load
label1.Text="Abc";
That will go to ViewState of Control where Label is Declared. So IN nutshell Assigning
Initial Values of controls in Page_ load unnecessary adds burden to <place><placename>View <placetype>State. I will
explain the reason for this in later FAQ's where i have talked about <place><placename>View <placetype>State Tracking.
It is Very easy to do such mistakes and once you know what the right way is, it is very
easy to Fix.


2) As Explained in Above Example if Viewstate is not stored in Control then How
Any control tracks It Values across pstbacks?

First of all this is a common misconception that Control will not remember its postback
data if I set EnableViewState=False.Let us take an example. Supoouse I declare a
DropDownList as shown below in the Page

C#
<asp:DropdownList id="lstStates" runat="server" DataTextField="StateName"
 
DataValueField="StateCode" EnableViewState="False"/>
  
protected override void OnLoad(EventArgs args) {
 


<pre>if(!this.IsPostBack)
 {
   this.lstStates.DataSource = QueryDatabase(); 
 
   this.lstStates.DataBind(); 
}
base.OnLoad(e); 
}

Above Code is Very wrong from Performance Point Of view. What is Happing behind the
Scenes is you are Sending Back And Forth the <place><placename>Whole <placetype>state list across the <place><placename>Wire <placename>IN View

<placetype>State.

To Solve this problem we can Set EnableViewState=false to Dropdown List and get rid of !
this.IsPostBack and rebind all the Time. It is more Cheap then Having to do only When
There is not a Post Back.

WAIT!!!! Now If i code something like this as shown below SelectedValue property will
reset back to defaults in Page_load

<pre><asp:DropdownList id="lstStates" runat="server" DataTextField="StateName" 
DataValueField="StateCode" EnableViewState="False"/> 
  
protected override void OnLoad(EventArgs args) { 
 
this.lstStates.DataSource = QueryDatabase(); 
 
this.lstStates.DataBind(); 
  
base.OnLoad(e); 
 
}

With above code we no longer is saving the state list in View State But Now Dropdown is
not remembering its PostBackValue. This is happening because as soon as We rebind All
Post back data is Gone and Selected Value property has default value.

So What is The Solution?

Solution Is PostBackData Is loaded Before Page_Load and After OnInit so if i Bind the
control before post back data is filled then You can still get the Selected Value.

So following code will fix the problem.

<pre>protected override void OnInit(EventArgs args) { 
 
this.lstStates.DataSource = QueryDatabase(); 
 
this.lstStates.DataBind(); 
  
base.OnInit(e); 
 
}

THis Solution will Work Fine. Now In Page_Load you will see right Posted Values from Post
Back even if we are rebinding again and Again. IN This solution View state Doesn't store
list of countries and at the same time You are Getting Post back Data. So it is a Win Win
situaltion. Remember SelectedINdexChanged Event will not work if EnableViewState=False.

3) In the Above Example If I have a Dropdown List and I Rebind All the Time IN
Page Load and also keep the EnableViewState=true Why I am not getting
SelectedINdexChanged Event?

This is very common problem in code. Please move all the Binding to Page_init before post
back data is Loaded then You should be OK.

4) What is ViewState Tracking??? How ASP.NET remembers Changes if it doesn't
store initial Values defined in ASPX file as explained in Item Number 1)?

<place><placename>View <placetype>State has a Method called TrackViewState() . This method once called for a Control,
Any changes done after that is tracked in View State as Hidden Form Filed which you see
all the time in View Source Window. There are Two Methods of Page or Control which is
called during the Page life cycle. Page calls LoadViewState during Post Back before
Page_load and it calls SaveViewState before Serializing the Data in Hidden Form Filed.
SaveViewState() of Page calls SaveViewState of all the Child Controls inside It. At This
Point Only Data Which Are Marked as Dirty in View State Bag is serialized. Now The
Question is Where Does framework calls TrackViewState? Answer is in the following
paragraph

Suppose you have this code

ViewState["key"]="abc"; 
 ViewState["Key']="yzs";// Till this moment these values will not go 
to Hidden Form Field. 
 ViewState.TrackViewState();// 
 ViewState["Key']="hhghjg" ;// this will be tracked and Will go 
//to Hidden Form Field. 

You Don't have to Explicitly call TrackViewState in your Control. It is done automatically
During the OnInit Phase of Control. So if you set any property in the Control's OnInit
phase, you can avoid having those values being tracked in View State. After that Any
property you set will go to ViewState of that control and will be tracked.

lets Supoose I have a UserControl which has Label lblDate. IN User Control OnINit() Event
I have following code

<pre>protected override void OnInit(EventArgs args) { 
 
this.lblDate.Text = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); 
 
base.OnInit(e); 
 
}

Does this mean that Text Value Of Label will Not go to ViewState since i have set the
Label's Text property in ONINit of My user control?. If you are thinking above code is
correct then you are wrong. OnInit Of Child Controls(Label) here is already called before
OnInit of UserControl is called So Its ViewState is Already Tracked.

You Might ask Why Can't just I disable The ViewState of Label and Get Rid of all the
problems.That Will Work but Suppose You Have a Situation where Clicking on a button
Which Does the Post Back And button Click handler changes the Label Text like below

private void cmdRemoveDate_Click(object sender, EventArgs args) { 
 
this.lblDate.Text = "--/--/---- --:--:--"; 
 
} 

You Might Think that During the Post Back I Will See the Empty Date After Button
Click ,since View State is not Enabled in Label , I am not saving in the View State default
Values Which is Current Date.Well !! You are wrong here again? Answer is If you Disable
The View State Then On Post Back You will See Current Date Again Which is Not What
You want. What You want is Not to Keep The original Values in View State But any
changes there after should be tracked.

Unfortunately there is No simple Solution. As i explained earlier best Place is before The
OnInit Of Label Itself is called. If we set the Value There then that Value Will not be
tracked in Hidden Field Unless We make Changes After OnInit OF label Is Done.

So there are two Solutions

1. Declaratively hook into the Init event:

<asp:Label id="Label2" runat="server" OnInit="lblDate_Init" /> 


This works because the OnInit attribute is processed before the label's own OnInit event
occurs, giving us an opportunity to manipulate it before it beings tracking ViewState
changes. Our event handler would set its text.


2. Create a custom control:

<pre>public class DateTimeLabel : Label { 
 
public DateTimeLabel() { 
 
this.Text = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); 
 
} 
}

Then instead of a regular label on the form, a DateTimeLabel is used. Since the control is
initializing it's own state, it can do so before tracking begins. It does it during the
constructor if possible, so that a declared value will be honored.

This is Just an Example Of Label's. This happens for all the controls So it is better to Set
The EnableViewState="false" unless you have a Situation Like above where you need to
track the changes but still don't want to track the initial Values.

Always Initialize IN OnINit of Your Control If you want to use the PostBack values of Label
or Any control as i have explained in DropDownExample above.

5) What is the Alternative to Label??

Label unecesary adds SPAN tag in HTML form and also sts the <place><placename>View <placetype>State=true. In your
ASPX or ASCX file do this

<%= Xyz() %> . This has no issue of adding values in <place><placename>View <placetype>State.

If you write <asp:Label ID="jjbb" runat="Server" Text="<%= Xyz() %>" ASP.NET will give an Error.

If you write <asp:Label ID="jbj" runat="Server" Text="<%# Xyz() %>"> then this will Add the Value IN View Sate Because Binding Happens Late In The Page Life
Cycle After OnINit of Label Which Just Picks the Default value from ASCX file.

6) What About Dynamic Controls??

This is What I got from web (David Creed article)on Dynamic control.

This is the same problem as before, but since you are in more control of the situation, it is much easier to solve. Let's say Joe has written a custom control that at some point is
dynamically creating a Label.

public class JoesCustomControl : Control { 
protected override void CreateChildControls() { 
Label l = new Label(); 
this.Controls.Add(l); 
l.Text = "Joe's label!"; 
 
} 


}

Hmmm. When do dynamically created controls begin tracking <place><placename>View <placetype>State? You can create
and add dynamically created controls to your controls collection at almost any time during
the page lifecycle, but ASP.NET uses the OnInit phase to start <place><placename>View <placetype>State tracking.
Won't our dynamic label miss out on that event? No. The trick is, Controls.Add() isn't just
a simple collection add request. It does much more. As soon as a dynamic control is
added to the control collection of a control that is rooted in the page (if you follow its
parent controls eventually you get to the page), ASP.NET plays "catch up" with the event
sequence in that control and any controls it contains. So let's say you add a control
dynamically in the OnPreRender event (although there plenty of reasons why you would
not want to do that). At that point, your OnInit, LoadViewState, LoadPostBackData, and
OnLoad events have transpired. The second the control enters your control collection, all
of these events happen within the control. That means my friends the dynamic control is
tracking <place><placename>View <placetype>State immediately after you add it. Besides your constructor, the earliest
you can add dynamic controls is in OnInit, where child controls are already tracking
ViewState. In Joe's control, he's adding them in the CreateChildControls() method, which
ASP.NET calls whenever it needs to make sure child controls exist (when it is called can
vary based on whether you are an INamingContainer, whether it is a postback, and
whether anything else calls EnsureChildControl()). The latest this can happen is
OnPreRender, but if it happens any time after or during OnInit, you will be dirtying
ViewState again, Joe. The solution is simple but easy to miss:

<p style="MARGIN-BOTTOM: 12pt">public class JoesCustomControl : Control 
{ protected override void CreateChildControls()
 { Label l = new Label();
 l.Text = "Joe's label!";
 this.Controls.Add(l); } 
}










</p>

Subtle. Instead of initializing the label's text after adding it to the control collection, Joe
initializes it before it is added. This ensures without a doubt that the Label is not tracking
ViewState when it is initialized. Actually you can use this trick to do more than just
initialize simple properties. You can databind controls even before they are part of the
control tree. Remember our US State dropdown list example? If we can create that
dropdown list dynamically, we can solve that problem without even disabling its
ViewState:

<pre>public class JoesCustomControl : Control { 
 
protected override void OnInit(EventArgs args) { 
 
DropDownList states = new DropDownList(); 
 states.DataSource = this.GetUSStatesFromDatabase(); 
 states.DataBind(); 
this.Controls.Add(states); 
 
} 
} 

It works amazingly well. The dropdown list will behave as if the states are simply built-in
list items. They are not persisted in ViewState, yet ViewState is still enabled on the
control, meaning you can still take advantage of its ViewState dependant features like
the OnSelectedIndexChanged event. You can even do this with DataGrids, although that
depends on how you are using it (you will run into problems if you are using sorting,
paging, or using the SelectedIndex feature).

Thanks

Verinder

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralConfusing Topic Pin
VipinGarg18-Oct-07 2:21
VipinGarg18-Oct-07 2:21 
GeneralSetting Text in OnInit... Pin
d2bishop8-Aug-07 5:27
d2bishop8-Aug-07 5:27 
GeneralGreat Pin
manofatlantic9-Jul-07 4:59
manofatlantic9-Jul-07 4:59 
GeneralGood effort, bad writing.. Pin
reshmaalam6-Apr-07 7:47
reshmaalam6-Apr-07 7:47 
AnswerRe: Good effort, bad writing.. Pin
verinder_bindra7-Apr-07 4:43
verinder_bindra7-Apr-07 4:43 
QuestionWouldn't storing ViewState on server solev all this? Pin
Abi Bellamkonda21-Feb-07 11:52
Abi Bellamkonda21-Feb-07 11:52 
AnswerRe: Wouldn't storing ViewState on server solev all this? Pin
verinder_bindra21-Feb-07 13:17
verinder_bindra21-Feb-07 13:17 
GeneralRe: Wouldn't storing ViewState on server solev all this? Pin
Abi Bellamkonda21-Feb-07 16:51
Abi Bellamkonda21-Feb-07 16:51 
GeneralProof read submissions Pin
Jeff W Welch20-Feb-07 12:22
Jeff W Welch20-Feb-07 12:22 
GeneralRe: Proof read submissions Pin
verinder_bindra20-Feb-07 13:20
verinder_bindra20-Feb-07 13:20 
AnswerRe: Proof read submissions Pin
verinder_bindra20-Feb-07 16:55
verinder_bindra20-Feb-07 16:55 
GeneralSpelling Mistakes Pin
rrobbins20-Feb-07 11:54
professionalrrobbins20-Feb-07 11:54 
AnswerRe: Spelling Mistakes Pin
verinder_bindra20-Feb-07 13:22
verinder_bindra20-Feb-07 13:22 
GeneralArticle format Pin
TBermudez20-Feb-07 10:56
TBermudez20-Feb-07 10:56 
GeneralRe: Article format Pin
verinder_bindra20-Feb-07 12:01
verinder_bindra20-Feb-07 12:01 
AnswerRe: Article format Pin
verinder_bindra20-Feb-07 13:21
verinder_bindra20-Feb-07 13:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.