When to save a variable in viewstate? - asp.net

I have searched the web for the answer and saw that mostly variables are saved in viewstate on page.prerender event. Then the value of the variable is set back in page load event.
However, when I save a variable in viewstate on prerender or load events, how can viewstate store the value of the variable after it is changed dynamically on codebehind?
Let's say, after page is loaded, user clicked a button which changes the value of the variable in its onClick event. Then the postback event raised since the button was clicked. According to me, the new value should have been lost and cannot be saved in the viewstate if the variable is saved in the viewstate only in prerender event. Because on postback the prerender event wont fire and the value cannot be saved.
Shouldn't I save the variable in the viewstate just before the postback event rises?
Am I wrong? If so, how can viewstate store the new value of the variable if the viewstate is saved in prerender event?
Thanks for the answer in advance..

I suspect you're confusing saving ViewState, ie. serializing the ViewState collection in memory to a string representation or to an intermediate object that can be serialized easily, with actually modifying that ViewState in-memory object with its regular accessor methods.
What you may be hearing is that the SaveViewState() method is called after PreRender event. But that has little to do with when you get to modify the contents of the ViewState collection.
Checkout points 7. Prerender the Objects and 8. ViewState Saved in the article The ASP.NET Page Life Cycle. There's a good MSDN article that touches on this as well.
(source: microsoft.com)

As per ASP.Net Page Lifecycle Overview (emphasis is mine)
PreLoad()
Raised after the page loads view state for itself and all controls, and after it processes postback data that is included with the Request() instance.
....
SaveStateComplete()
Raised after view state and control state have been saved for the page and for all controls. Any changes to the page or controls at this point affect rendering, but the changes will not be retrieved on the next postback.
As both Control Events and the PreRender event occur between these two, then your data should be persisted in ViewState.

Viewstate is maintained via a hidden field, so Postback has to finish before it's "set".
If you're setting it and trying to read it in the same page cycle it not going to work. You might try using the Session object, which get/sets values into memory.

Related

ASP.NET: How to repopulate dynamically added controls to appease a dynamically added RequiredFieldValidator?

I'm adding dynamic controls to a page based on data from a database to generate RadioButtonList questions.
Sometimes the questions are required, in which case after the data is retrieved from the database and the RadioButtonList is populated, I dynamically add a RequiredFieldValidator for the RadioButtonList.
The problem arises on postback, when in Page_Load() I execute Page.Validate() which always fails. I discovered that this is because the controls are being re-added on post-back but they aren't repopulated with the user's responses.
My question is:
When can I grab the user's response once they click "Submit", where do I store it, and what's the best way to bring it back so that Page.Validate() validates against controls with the proper responses?
Instead of creating the validation controls in Page_Load (or in a function that's called from within page_Load) do so in Page_Init
For more info see the Page Lifecycle:
In the Page Lifecycle, putting it in Page_Init allows the controls to be created on each page load, but BEFORE the viewstate values are applied. This means that the controls are created, and then the user selection is applied.
If you have it in Page_Load, then the controls are created AFTER the Viewstate values are applied. This means that the controls are just created from scratch after the viewstate has been applied, resetting everything to the default value.
Actually, this page says it better:
During page initialization, controls on the page are available and
each control's UniqueID property is set. Any themes are also applied
to the page. If the current request is a postback, the postback data
has not yet been loaded and control property values have not been
restored to the values from view state.
During load, if the current
request is a postback, control properties are loaded with information
recovered from view state and control state.
Use Page_Init when you
have to create controls dynamically. The controls are created every
time that the page is run. The best place to do this is in the
Page_Init function.

asp.net load postback data and raise postback event viewstate interaction

I'm reading up to get a better idea of how viewstate works in asp.net webforms and have been reading this article.
One part that I don't quite understand is the Stage 5 - Raise postback event, it says that this stage does not make use of any viewstate information to raise the events (ie. TextChanged).
I thought that the viewstate would be sent back with the page on the postback and after the control tree had been populated the values from the viewstate would then be loaded in and then after that the control would interrogate the new form values comparing them against the current ones loaded from viewstate in order to tell which Changed() events it needs to raise.
If this event doesn't interact with viewstate how can it tell whether a value has changed or if it is still the same from the previous load?
Daniel, you are correct in your assumption - view state is used to determine whether a change-related event needs to be raised. That includes things like the TextChanged event on the TextBox and the SelectedIndexChanged event on the DropDownList, among others.
If you haven't read this article yet, I highly recommend it: Truly Understanding View State. It's an informative write up by Dave Reed.
Thanks!
In the case of TextChanged events, it does look at the viewstate to determine if it gets raised or not - see the answer to question 6215046:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.textbox.ontextchanged.aspx
A TextBox control must persist some values between posts to the server for this event >> to work correctly. Be sure that view state is enabled for this control.
Try enabling ViewState for TextBox.

Why is it recommended to save viewstate values in the PreRender event call?

I am trying to persist member variables by saving them in the ViewState (only a few small variables) however I read up and I gather its better to save them into the ViewState at the PreRender stage than PageLoad?
I can see that the ViewState can be saved to anytime before Page rendering, but does it make any difference in PreRender or PageLoad?
No, there isn't a difference. You just need to save your variables to the ViewState after you are finished changing them. i.e. Don't save the variable to the ViewState in the Page_Load event if you change it again in PreRender.

ASP.NET: Viewstate and programmatically adding user controls

When programmatically adding user controls using LoadControl(string path), when, in the user control's page life cycle, does it initialize its sub-controls with its viewstate?
I'm asking this question because one of my user controls that's being programmatically loaded has a TextBox control that is not being initialized/loaded by it's viewstate on PostBack on the Page_Load event (which is not the case for a regular .aspx pages and hence my confusion). Overall, I need to retrieve values from the Textbox control.
Thanks
ViewState is loaded before the Page_Load event. If you want your control to work with ViewState, you need to load it and add it to the page before that event — usually on PreInit.
The life cycle reference is here:
http://msdn.microsoft.com/en-us/library/ms178472.aspx?ppud=4
Read the description for the Pre Load event, which immediately precedes Page Load:
Use this event if you need to perform processing on your page or control before the Load event.
Before the Page instance raises this event, it loads view state for itself and all controls, and then processes any postback data included with the Request instance.
Thus by Pre Load time it's already too late. Also, the description for the PreInit event specifically mentions that it's the place to "create or re-create dynamic controls."

ASP.Net: User controls added to placeholder dynamically cannot retrieve values

I am adding some user controls dynamically to a PlaceHolder server control. My user control consists of some labels and some textbox controls.
When I submit the form and try to view the contents of the textboxes (within each user control) on the server, they are empty.
When the postback completes, the textboxes have the data that I entered prior to postback. This tells me that the text in the boxes are being retained through ViewState. I just don't know why I can't find them when I'm debugging.
Can someone please tell me why I would not be seeing the data the user entered on the server?
Thanks for any help.
This is based on .NET v1 event sequence, but it should give you the idea:
Initialize (Init event)
Begin Tracking View State (checks if postback)
Load View State (if postback)
Load Postback Data (if postback)
Load (Load event)
Raise Changed Events (if postback)
Raise Postback Events (if postback)
PreRender (PreRender event)
Save View State
Render
Unload (Unload event)
Dispose
As you can see, the loading of ViewState data back to the controls happen before the Load event. So in order for your dynamically-added controls to "retain" those values, they have to be present for the ASP.NET page to reload the values in the first place. You would have to re-create those controls at the Init stage, before Load View State occurs.
I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If IsPostBack Then
CreateMyControls()
End If
End Sub
I believe you'll need to add the UserControl to the PlaceHolder during the Init phase of the page life cycle, in order to get the ViewState to be filled in by the Load phase to read those values. Is this the order in which you're loading those?
Ensure you are defining your dynamic controls at the class level and adding them to the ASP container:
Private dynControl As ASP.MyNamespace_MyControl_ascx
And when you instantiate the control, ensure you call LoadControl so the object is added properly:
dynControl = CType(LoadControl("~/MyNamespace/MyControl/MyControl.ascx"), ASP.MyNamespace_MyControl_ascx)
You have to create your controls in the Page_PreInit event handler. The ASP.NET server control model is tricky; you have to fully understand the page lifecycle to do it right.
As others have said, any form of control manipulation must be done before viewstate is created.
Here is a good link on the page lifecycle to help you out:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
We have experienced the same thing and have handled it by using ghost controls on page_load that have the exact same .ID and then the post back picks up the events and the data. As others said it's the dynamic adding of the control after the init stages that the state is built already and controls added after aren't stored.
Hope this helps a bit.
I also want to add that I've seen user controls work the way that you'd expect them to just by setting the Control.ID property at run time. If you do not set the ID, items may get built in a different order and work oddly.

Resources