Not understanding why ViewState is not increasing in size when changing content?
I thought I understood ViewState, but this is a bit of a weird one.
I have a page of 1000 labels and textboxes like this:
<dt>
<asp:Label runat="server" ID="Label1" AssociatedControlID="TextBox1">Label1</asp:Label>
</dt>
<dd>
<asp:TextBox runat="server" ID="TextBox1"></asp:TextBox>
</dd>
All increme开发者_StackOverflow中文版ting by 1. I've added a button to the top:
<asp:Button runat="server" ID="PostBack" Text="Post it all back!" OnClick="ChangeValues"/>
and the corresponding code is:
protected void ChangeValues(object sender, EventArgs e)
{
for (int i = 1; i <= 1000; i++)
{
string textBoxId = "TextBox" + i;
((TextBox)Page.FindControl(textBoxId)).Text = textBoxId;
}
}
So what I would understand is:
- First page load, the controls are set up initially, therefore no control viewstate created
- On postback, the button click is modifying the controls. Therefore, when generating the ViewState, .NET realises that the text has changed from the default and records this in the viewstate.
Now for 1000 controls, you'd expect it to be reasonably big, well bigger than this:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNjYzODc0MDE1ZGQRGHqYtZTbbkevIfg33I4Wja+xfz0at0+fDMS72BtZNA==" />
I think I'm missing a trick here. I have turned on Trace=true
, and noticed that all of the ViewState is still 0 bytes. EnableViewState
and ViewStateMode
are not declared in the <@Page
directive, so ViewState is on and working.
Can anyone help me understand why I am misunderstanding how this is working?
Perhaps it's because the Text property of a TextBox doesn't need to be saved to ViewState as it will be rendered to the page and posted back with the post data.
If you look at the implementation of TextBox
with Reflector you'll see it has a property SaveTextViewState
that controls whether the Text property needs to be saved to ViewState:
protected override object SaveViewState()
{
if (!this.SaveTextViewState)
{
// This means the Text property will not be saved to ViewState
this.ViewState.SetItemDirty("Text", false);
}
return base.SaveViewState();
}
In cases where saving the ViewState is necessary (e.g. the TextBox is not Visible), SaveTextViewState
returns true and the Text property is saved to ViewState.
UPDATE
According to Reflector the implementation of the SaveTextViewState
property (the property used to determine whether Text
needs to be persisted to ViewState) is as follows:
private bool SaveTextViewState
{
get
{
if (this.TextMode == TextBoxMode.Password) return false;
}
if (((base.Events[EventTextChanged] == null) &&
base.IsEnabled) &&
((this.Visible && !this.ReadOnly) &&
(base.GetType() == typeof(TextBox))))
{
return false;
}
return true;
}
}
I.e. Text
is persisted to ViewState if it's not a password textbox and any of the following are true:
there exists a handler for the TextChanged event (in this case it needs the original value to detect if the text has changed)
the control is disabled (in which case the Text won't be posted back)
the control is not visible (in which case it won't be rendered)
the control is readonly (Text won't be posted back)
the control type is not
TextBox
(don't optimize by suppressing ViewState as this may impact the implementation of a derived control).
Essentially an optimization that suppresses ViewState if it's sure it won't be needed.
The answer is Controls which implement IPostBackEventHandler
like Textbox, Checkbox
, etc. will retain the state even after disabling the viewstate
. The reason is during the Load Postback Data stage, these controls will get state information from Posted back form.
But controls like label which do not implement IPostBackEventHandler will not get any state information from posted back data and hence depend entirely on viewstate to maintain the state.
精彩评论