Let’s build a simple Web application to examine how
ViewState
works.
Create a blank Web project and paste the code given below in
the page:
<script runat="server">
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles btnSubmit.Click
lblMessage.Text = "Goodbye everyone"
lblMessage1.Text = "Goodbye everyone"
txtMessage.Text = "Goodbye everyone"
txtMessage1.Text = "Goodbye everyone"
End Sub
</script>
<form id="form1" runat="server">
<asp:Label runat="server" ID="lblMessage" EnableViewState =true
Text="Hello World"></asp:Label>
<asp:Label runat="server" ID="lblMessage1" EnableViewState =false
Text="Hello World"></asp:Label>
<asp:Textbox runat="server" ID="txtMessage" EnableViewState =true
Text="Hello World"></asp:Textbox>
<asp:Textbox runat="server" ID="txtMessage1" EnableViewState =false
Text="Hello World"></asp:Textbox>
<br />
<asp:Button runat="server"
Text="Change Message" ID="btnSubmit"></asp:Button>
<br />
<asp:Button ID="btnEmptyPostBack" runat="server" Text="Empty Postback"></asp:Button>
</form>
The page rendered will have four controls (two text boxes and
two labels) initialized with
Hello
World
and two
buttons.
Click on the Change Message button, the value in controls will be
changed to
Goodbye
Everyone
.
Now click on the Empty Postback button.
The expected result is, after postback the Textbox (
txtMessage
) and
label (lblMessage
) with EnableViewState
= false
should
not retain the value and hence the value should be Hello world
, while the controls with ViewState
enabled
(txtMessage1
and lblMessage1
)
should retain the value and hence value should be Goodbye world
.
But this does not happen. Both the Textbox will maintain the
value irrespective of whether
ViewState
is enabled or disabled, but in the case of
label control if ViewState
is disabled, the value we changed
programmatically is not retained.
Let's examine why this happens?
Page LifeCycle and ViewState
In page life cycle, two events are associated with
ViewState
:
·
Load View State: This stage follows the initialization stage of page
lifecycle. During this stage,
ViewState
information saved in the
previous postback is loaded into controls. As there is no need to check and
load previous data, when the page is loaded for the first time this stage will
not happen. On subsequent postback of the page as there may be previous data
for the controls, the page will go through this stage.
·
Save View State: This stage precedes the render stage of the page. During
this stage, current state (
value
) of controls is serialized
into 64 bit encoded string
and persisted in the hidden
control (__ViewState
) in the page.
·
Load Postback Data stage: Though this stage has nothing to do with
ViewState
, it causes most of the
misconception among developers. This stage only happens when the page has been
posted back. ASP.NET controls which implement IPostBackEventHandler
will update its value (state
) from the appropriate
postback data. The important things to note about this stage are as follows:
1.
State (
value
) of controls are NOT
retrieved from ViewState
but from posted back form.
2.
Page class will hand over the posted back data to only those
controls which implement
IPostBackEventHandler
.
3.
This stage follows the Load View State stage, in other words
state of controls set during the Load View State stage will be overwritten in
this stage.
Hey sivaraj,
Thank you for all the analysis. The post in indeed really helpful but I see one flaw in it. The interface that you've talked about is IPostBackEventHandler. It should actually be IPostBackDataHandler. IPostbackDataHandler is the interface implementing which helps controls like text box restore their text data on page post back even if their view state is disabled. TextBox control doesn't implement IPostbackEventHandler interface at all. You can check what all controls implement IPostbackEventHandler interface at following link :
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackeventhandler(v=VS.71).aspx[^]
You can check what all controls implement IPostbackDataHandler interface at following link :
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackdatahandler(VS.71).aspx[^]
Thank you for all the analysis. The post in indeed really helpful but I see one flaw in it. The interface that you've talked about is IPostBackEventHandler. It should actually be IPostBackDataHandler. IPostbackDataHandler is the interface implementing which helps controls like text box restore their text data on page post back even if their view state is disabled. TextBox control doesn't implement IPostbackEventHandler interface at all. You can check what all controls implement IPostbackEventHandler interface at following link :
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackeventhandler(v=VS.71).aspx[^]
You can check what all controls implement IPostbackDataHandler interface at following link :
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackdatahandler(VS.71).aspx[^]
Answers
Now with the above information, let us try to answer the
question:
Why some controls retain values even after
disabling the ViewState while others do not?
The answer is Controls which implements
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.
Following are the changes in
textbox
during the page life cycle.
Textbox with ViewState Enabled
Page
Events
|
Page
is visited for first time
|
On
click of “Change Message” button
|
On
click of “Empty Post back” button
|
Init
|
Textbox is
set value Hello
World |
Textbox is
set value Hello
World |
Textbox is
set value Hello
World |
Load
View State
|
In section "Textbox with
ViewState Enabled" the cell (Load View State, On click of “Change
Message” button) should read as "Texbox is set with value Hello World
from ViewState"
"Texbox is set with value Hello
World from ViewState"
|
Textbox is
set with value Good
Bye Everyone from ViewState |
|
Load
Post back data stage
|
Postback
data is
Hello
World so Textbox is set with Hello
World |
Postback
data is
Goodbye
Everyone so Textbox is set withGoodbye Everyone |
|
Controls
Postback event (button click )
|
Textbox is
set with Goodbye
everyone |
||
Save
view state
|
Hello World is saved toViewState |
Goodbye Everyone is saved to ViewState |
Goodbye Everyone is saved toViewState |
Render
|
Textbox is rendered with textHello world |
Textbox is rendered with text Goodbye
Everyone |
Textbox is rendered with textGoodbye Everyone |
Textbox with ViewState Disabled
Page
Events
|
Page
is visited for first time
|
On
click of “Change Message” button
|
On
click of “Empty Post back” button
|
Init
|
Textbox is
set value Hello
World |
Textbox is
set value Hello
World |
Textbox is
set value Hello
World |
Load
View State
|
In the section "Textbox with ViewState Disabled" the cell
(Load View State, On click of “Empty Post back” button) should be empty
because as the section heading explains it has no view state from previous
page. (Textbox is set with value Good Bye Everyone from ViewState) |
||
Load
Post back data stage
|
Postback
data is
Hello
World so Textbox is set with Hello
World |
Postback
data is
Goodbye
Everyone so Textbox is set withGoodbye Everyone |
|
Controls
Postback event (button click )
|
Textbox is
set with Goodbye
everyone |
||
Save
view state
|
|||
Render
|
Textbox is rendered with textHello world |
Textbox is rendered with text Goodbye
Everyone |
Textbox is rendered with textGoodbye Everyone |
Label with ViewState Enabled
Page
Events
|
Page
is visited for first time
|
On
click of “Change Message” button
|
On
click of “Empty Post back” button
|
Init
|
Label is
set valueHello World |
Label is
set value Hello
World |
Label is
set value Hello
World |
Load
View State
|
In section "Label with ViewState
Enabled" the cell (Load View State, On click of “Change Message” button)
should read as "Label is set with value Hello World from ViewState"
|
Label is
set with value Good
Bye Everyone from ViewState |
|
Load
Post back data stage
|
|||
Controls
Postback event (button click)
|
Label is
set withGoodbye everyone |
||
Save
view state
|
Hello World is saved to label |
Goodbye Everyone is saved to ViewState |
Goodbye Everyone is saved toViewState |
Render
|
Label is rendered with text Hello
world |
Label is rendered with text Goodbye
Everyone |
Label is rendered with textGoodbye Everyone |
Label with ViewState Disabled
Page
Events
|
Page
is visited for first time
|
On
click of “Change Message” button
|
On
click of “Empty Post back” button
|
Init
|
Label is
set valueHello World |
Label is
set value Hello
World |
Label is
set valueHello World |
Load
View State
|
|||
Load
Post back data stage
|
|||
Controls
Postback event (button click )
|
Label is
set with Goodbye
everyone |
||
Save
view state
|
|||
Render
|
Label is rendered with text Hello
world |
Label is rendered with textGoodbye Everyone |
Label is rendered with text Hello
World |
In page life cycle, two events are
associated with ViewState:
·
Load View State: This stage follows the initialization stage of page lifecycle.
During this stage, ViewState information saved in the previous postback is loaded into
controls. As there is no need to check and load previous data, when the page is
loaded for the first time this stage will not happen. On subsequent postback of
the page as there may be previous data for the controls, the page will go
through this stage.
·
Save View State: This stage precedes the render stage of the page. During this
stage, current state (value) of controls is serialized into 64 bit encoded string and persisted in the hidden control (__ViewState) in the page.
·
Load Postback Data stage: Though this stage has nothing to do with ViewState, it causes most of the misconception
among developers. This stage only happens when the page has been posted back.
ASP.NET controls which implement IPostBackDataHandler will update its value (state) from the appropriate postback data. The important things to
note about this stage are as follows:
1.
State (value) of controls are NOT retrieved from ViewState but from posted back form.
2.
Page class will hand over the posted
back data to only those controls which implement IPostBackDataHandler.
3.
This stage follows the Load View
State stage, in other words state of controls set during the Load View State
stage will be overwritten in this stage.
There is one correction
IPostBackDataHandler
IPostBackEventHandler
IPostBackEventHandler Interface
Button,Linkbutton
etc control implements this interface
******************
Where you can add dynamic cotrol to the Page At page _init.
http://aspnet.4guysfromrolla.com/articles/092904-1.aspx
Adding Controls at the Right Time
We already know that when adding controls dynamically through the page's code portion the controls must be added on every postback. But when in the page lifecycle should the controls be added? At first guess, we might decide to put such code in the
Page_Load
event handler, causing the controls to be added during the Load stage of the page's lifecycle. This would work fine if we don't need to worry about saving the controls' view state across postbacks, but if we do need to persist the view state of the dynamically added controls the Load stage is not where we should be adding these controls.
If we need our dynamically added controls to maintain their view state it is paramount that these controls be added before the Load View State stage. That is, these controls must exist within the page's control hierarchy before the view state is loaded. There's only one stage before Load View State - Initialization. That means, if we want our dynamic controls to persist view state we must add them to the control hierarchy in the page's
Init
event.
If you are using Visual Studio .NET, the code-behind class already contains an event handler for the page's
Init
event. This event handler (named Page_Init
in VB.NET code-behind classes and OnInit
in C# code-behind classes) is tucked away in the hidden "Web Form Designer Generated Code" region. What I typically do is create a separate method in the code-behind class and simply call this method from the Init
event handler. Once you have configured everything so that the dynamic controls are added during the Initialization stage, you can then read/write the controls' properties in the Load stage. You'll find that the users' interactions with the dynamic controls remains "remembered" across postbacks if you follow this pattern.
No comments:
Post a Comment