ViewState and Dynamic Control
I thought I understand ViewState, until I came cross this exception:
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
This is a question asked by someone on a .NET mailing list. My first guess of what causing the problem is that on a page postback, when LoadViewState() is invoked to restore the saved ViewState values to the page and its controls (both Control tree and ViewState tree have been created at this stage), somehow, the ViewState tree doesn't match the control tree. So when ASP.NET tries to restore a ViewState value to a control, no control or a wrong control is found and then the exception occurs.
Note: the ViewState tree (type of Triplet or Pair) is NOT the ViewState property (type of StateBag) of the page or any of its controls. You can think it as an object representation of the ViewState value on the html page (the __VIEWSTATE hidden field), which contains all the values need to be written back to the controls during a page postback. If you don't change the default behavior, during the page initialize/load phrase, the ViewState tree will be created by de-serializing the value __VIEWSTATE field by LoadPageStateFromPersistenceMe
So, I thought I could reproduce same exception with something simple like this:
Defualt.aspx
Default.aspx.cs
public partial class _Default : Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!IsPostBack)
{
Button btnClickMe = new Button();
form1.Controls.Add(btnClickMe)
}
}
}
It is indeed a very simple page with a button named btnPostback created statically on .aspx file, and another button named btnClickMe created dynamically in Page.OnInit(), and I will not recreate the btnClickMe for postbacks. So on a page postback, by the time OnInit() and LoadPageStateFromPersistenceMe
To find out why, let's have a look of the actual ViewState value generated on the html page
“/
With a little help from ViewState Decoder I got this:
1469934321
There is no view state data for the neither of the buttons! I did expect something like for a control has empty state though.
So, I think here is the first thing I learned:
For a control on the Control tree, there may not be a corresponding item on the ViewState tree (if there is no state for this control need to be saved). If there is nothing found on ViewState tree for a control, the control’s LoadViewState() will not be invoked.
So, let's do something to make the button "dirty" and its ViewState saved.
public partial class _Default : Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!IsPostBack)
{
Button btnClickMe = new Button();
form1.Controls.Add(btnClickMe)
btnClickMe.Text = "Click me";
}
}
}
The ViewState now became:
/wEPDwUKMTQ2OT
"ViewState and Dynamic Control"
- ViewState and Dynamic Control (view on Google Sidewiki)