I sort of answered my own question I think but I want to make sure I am understanding correctly. I initially thought that when a user provided values in a form, that on postback the values were submitted as part of the Viewstate, because TextBox.Text is part of the viewstate. Now I have found that user supplied values actually aren't applied to the controls until after the OnLoad event. This confused me because I thought that viewstate was loaded into the controls before OnLoad(or when calling Controls.Add()). I have gone over the documentation on page and control lifecycles a few times and I am just now realizing that there was a different step for handling postback data(this step didn't appear in a lot of documentation :(
1) So postback data, the values user's type into the fields, is applied after the OnLoad event, and Viewstate data is applied just before the OnLoad event?
2) So essentially all this means is that on postback the server gets two values for a TextBox.Text property, the one in Viewstate, which is like the "old" value from the previous request, and the new value supplied by the user in the form?
3) Does the .net framework apply postback data the same was as Viewstate, in that it finds the appropriate control via it's ID property? This is important because I am creating controls dynamically and I may even have forms that change structure overtime and need to think about how I handle ID's. So far I haven't been setting the ID property and everything works fine but things may be more complicated later on.
4) Does viewstate data ever get modified at all on client side? Or is the viewstate identical to what was sent by the server in the previous request(assuming no tampering)? My impression used to be that the server encoded all the control properties into the viewstate, and on the client side when the user submitted the form, the viewstate field was decoded, modified, encoded, and submitted to the server with modifications. I assumed there was a bunch of javascript doing all this for me. Now I think I had it all wrong. Instead it seems that the Viewstate never changes on client side, and all the client changes are in the postback data such that the next request the server loads viewstate, loads postback, and provides a new updated viewstate in the next response?
1) Both are loaded before Load
2) Basically, yes
3) ViewState is applied first, then Post Data
To quote Scott Mitchell(see below)
dynamically added controls must be
programmatically added to the Web page
on each and every page visit. The best
time to add these controls is during
the initialization stage of the page
life cycle, which occurs before the
load view state stage. That is, we
want to have the control hierarchy
complete before the load view state
stage arrives. For this reason, it is
best to create an event handler for
the Page class's Init event in your
code-behind class, and add your
dynamic controls there.
4) Unless you're doing something way outside of the box, ViewState is never modified client-side. "ViewState" is an HTML form field and is processed on the server side.
Here's a few images from Understanding ASP.NET View State by Scott Mitchell that may help you.
(source: microsoft.com)
(source: microsoft.com)
Bonus Reading Material: http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
My impression used to be that the server encoded all the control
properties into the viewstate, and on the client side when the user
submitted the form, the viewstate field was decoded, modified,
encoded, and submitted to the server with modifications.
No, the point of the ViewState is simply to preserve the state of the page since the last "Save View State" page event, i.e. that event occurs shortly before the page is rendered to the client.
When the client makes selections to a dropdown box or changes text in a textbox the hidden ViewState property, which exists on the client page as a static HTML tag, is not dynamically changing / encoding those values, it remains the same as when the page was originally rendered.
So how is the new state of the page being preserved, i.e. how are user dropdown selections and text box values retained in ASP controls? Those dropdown selections and text box values are captured in Post Back data.
A server control can indicate that it is interested in examining the posted back data by implementing the IPostBackDataHandler interface. In this stage in the page life cycle, the Page class enumerates the posted back form fields, and searches for the corresponding server control. If it finds the control, it checks to see if the control implements the IPostBackDataHandler interface. If it does, it hands off the appropriate postback data to the server control by calling the control's LoadPostData() method. The server control would then update its state based on this postback data.
- Scott Mitchell
Related
I am trying to design a page that handles both Employee and Station CRUD tasks depending on the user's preference. I have sub-classed UserControl to create an EditEntityControl and developed two custom controls that derive from this base class and each handle the CRUD activities for either the Employee or Station object.
When the user toggles the value in a dropdownlist, which triggers a postback, I want to dynamically load the correct control into the page. This works on the first load of each control, but when I try to reload the first control (after loading the second), I get the following error:
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.
I also see some strange behavior on the initial load of the second control where data bindings don't bind to the correct controls (setting the text of a button rather than a textbox on the control for example).
Is there a way to handle this scenario? Or, is there a way to clear out the ViewState and just re-request the page entirely to get around this error? It appears that if I could clear up this ViewState clutter/confusion between PostBacks, everything else is working as designed.
Great suggestions in the comments above, but what finally pointed me to the correct solution was Joel Coehoorn's answer on this question.
I load up the control OnInit, then in the SelectionChanged event blow away the OnInit changes and recreate the correct control as needed. Thanks for the additional suggestions about making unused controls invisible. I will keep that in mind for future reference.
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.
I have two Repeater controls, each hosted in a user control. Both user controls are contained in the same aspx page. Only one User Control is visible at any one time. The repeaters are comprised of checkboxes, and text boxes for user input.
The aspx page is configured with an Ajax ScriptManager; and contains several Ajax UpdatePanels. These UpdatePanels result in partial page post backs when text is changed in a textbox control in controls on the aspx page (this is not the behaviour for the Repeaters in the User Controls). Through use of several AsyncPostBackTriggers, various controls contained in the other UpdatePanels on the page have their content refreshed in response to the partial page post backs they are configured be notified about.
Depending on a radio button group selection, I set the visible property to true or false – as appropriate for the User control containing a repeater control. The Repeater control is then populated with data using databinding. All of this works.
However, when the Submit button is clicked, the Repeater control contains no data.
Given that I am not dynamically adding the Controls containing the Repeater controls (but using Visible true / false). I would have thought that the State of the fields and the data in the visible control would be preserved during the post back.
The User Controls are contained within the UpdatePanel that contains the Submit Button.
I have explicitly Enabled View state without any effect.
Am I correct in assuming that I should not have to do any explicit handling of data changes the user makes (via client side script and manipulation of an Data Structure Representing the Repeater Data); and the View State should maintain the data I need to access on the server when submitted?
I do not believe that it is the User Control visible state changes that are causing the issue because when the page is initially loaded on of the User controls is populated with dummy rows (so it displays).
I am suspicious that because the visible state of the controls is changed during partial page post back, that the Page View State ends up with no knowledge of the User Control and therefore cannot track its data (or changes).
I have investigated a lot of similar sounding posts but so far do not feel that I have come across a solid explanation that can help me understand and fix the issue.
Hopefully someone can help.
I must be the only person who was unaware of the finer points of DataBind() method; be it called on a specific control being bound to data; or on the page itself. I hope the below helps others who find themselves in a position where data binding appears to be inexplicably lost'.
My problem was that my page was pretty complex. It has several User Controls on it. The problem was that in these User Controls, I was calling Page.DataBind() in the Page_Load event handler to 're-bind' the page data on PostBacks. This resulted in the Repeater control located on another User Control, to lose its data binding.
Removing the Page.DataBind method call from each of the User Controls on the Page_Load event handler method resolved the problem. It had nothing to do with Update panels / refreshes etc.
I'm looking for an easy way to explain this to someone. Apologies if it has been asked before.
It is a way to persist the page state between postbacks on the client. It represents a serialized string of the state of a page stored inside a hidden field and posted to the server at each request/postback (ASP.NET uses a single form and every time the user performs an action like clicking on the button this form is submitted to the server). Once the serialized state is submitted to the server it is capable of retrieving values that have been stored inside the view state.
Further reading: Understanding ASP.NET View State
By default, dynamic web pages do not keep their state. For example, you set a value for a variable in the page load event of asp.net page. You want to increment this variable when user clicks button. This is not possible because at every page postback, the variable is created and the page load event is executed therefore, the variable is set to the initial value. Then, you need a way to keep the value of variable even if page postback occurs. Viewstate can be used to solve this problem.
I have a simple user control containing two text boxes which I am adding to placeholder on Button Click event. I am storing the number(count) of clicks in View state and running a loop using count to create all previously added user control. I am also adding IDs to each User control (appending "UC" and count). I have also checked in view source the ids are same each time they are created. I have another button which basically does an post back. I have EnableViewState enabled ="true" in all controlls all the way up to Page Level.
My problem is that User Input does not persist on postback. please advice. Should this not be happening automatically for me?
Have a look at this:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
I've encountered minor problems with it on a web farm, but for simple deployments its use is pretty straightforward. (Comes with source code, and the web farm glitch is a pretty simple fix.)
You need to create your dynamic controls in the Page_PreInit event rather than Page_Load or in a Click event handler. That way, they'll be there before ViewState, and then your posted values are applied.
I thinks what is happening is that you are creating your controls during the click event handler which happens AFTER ViewState and PostBack have been applied. This means your controls will be created empty each time.