I have been writing a bunch of generic ASP.NET controls, and one thing I can't seem to wrap my mind around is when to store values in viewstate, and when to assume it's OK not to.
On one hand, it makes sense to store the entire state of the control in viewstate, including properties like:
Text box values entered by the user (or any form data)
Configuration options like height or page size
Even how the control has been composed - for example storing all the data a grid view is built from, or the grid itself.
Ignoring performance, the more you can shove in viewstate the better, because it means the control will behave exactly the same across postbacks and never "accidentally" revert a value or "forget" it was disabled. But viewstate is not free. Storing everything means the control will now output both the HTML and all its internal properties to create that HTML, which would almost always more than double the output.
My question is not about performance, but about strategy. On what criteria do I decide to put a property in viewstate? I was thinking something along these lines:
If the user can't change a property, then the server will always set it explicitly, so it's OK to leave it out of viewstate. Even for something like color=red, the user doesn't set this property directly; they will click a button elsewhere which indirectly sets this property. That button or its owner should keep the state, not the control that renders the color red.
This logic implies that the only properties that should go into viewstate would be:
Form elements like <input> (and with Request.Form[c.UniqueID] this can be avoided still)
Properties that the user can control interactively directly on the control.
Does this logic make sense? It seems weak and I'd like to hear more from experts.
Use ViewState for things that are not necessary for your control to work.
Use ControlState for things that are necessary for your control to work even if ViewState is disabled.
The initial values and the control hierarchy(even html-controls) are compiled into Temporary ASP.NET Files when the page is first requested. So they don't need to be stored anywhere when they are never changed (and even ViewState will not save them).
A control does only store properties in ViewState which have changed during the page's life-cycle(since TrackViewState). A control which state was changed is "dirty". For example if you change TextBox1.Text in page_load, ViewState.IsItemDirty("TextBox1.Text") would return true. These values will be stored in ViewState.
Look here and here. (I really recommend to read both articles)
Control State vs. View State Example
Check this article on MSDN covering when, where and what to use the plethora of state management options available in ASP.NET the view state section is posted below for convenience - checking your requirements against the advantages and disadvantages should guide you on usage on a case by case basis:
Whole article here: http://msdn.microsoft.com/en-us/library/z1hkazw7(v=vs.100).aspx
Viewstate Excerpt:
View State
Web Forms pages provide the ViewState property as a built-in structure
for automatically retaining values between multiple requests for the
same page. View state is maintained as a hidden field in the page. For
more information, see ASP.NET State Management Overview.
You can use view state to store your own page-specific values across
round trips when the page posts back to itself. For example, if your
application is maintaining user-specific information — that is,
information that is used in the page but is not necessarily part of
any control — you can store it in view state.
Advantages of using view state are:
No server resources are required The view state is contained in a
structure within the page code.
Simple implementation View state does not require any custom
programming to use. It is on by default to maintain state data on
controls.
Enhanced security features The values in view state are hashed,
compressed, and encoded for Unicode implementations, which provides
more security than using hidden fields.
Disadvantages of using view state are:
Performance considerations Because the view state is stored in the
page itself, storing large values can cause the page to slow down when
users display it and when they post it. This is especially relevant
for mobile devices, where bandwidth is often a limitation.
Device limitations Mobile devices might not have the memory capacity
to store a large amount of view-state data.
Potential security risks The view state is stored in one or more
hidden fields on the page. Although view state stores data in a hashed
format, it can still be tampered with. The information in the hidden
field can be seen if the page output source is viewed directly,
creating a potential security issue. For more information, see ASP.NET
Web Application Security and Basic Security Practices for Web
Applications.
I think you're right to be concerned about viewstate bloat, but what other options are available to you? If you don't store your variable data there, where will you put it? (You may wish to consider removing some configuration items- perhaps not let the user change so many properties).
Related
In asp.net, viewstae is it client variable or server variable? how much data can view state is store. I mean if i declare a view state, when more than one user accessing same page is the view state data can conflict or not?
You're really going to want to read this, It covers pretty much all of your questions:
http://msdn.microsoft.com/en-us/library/ms972976.aspx
THe ASP.NET ViewState is a client side hidden control which stores some state data for ASP.NET server controls. The content is Base64 encoded and can be seen with a decoder. It is only available on a postback to the same page. Different users have their own ViewState as it is a client side technology. You can store as much data as you want, but it affects the bandwith. In general you should watch out for large ViewState because it is also not very SEO friendly.
You can use it for your own data like this:
ViewState["myData1"] = someSerializableContent;
ViewState["myData2"] = someSerializableContent;
The ViewState is protected by a hash code to prevent manipulation.
EDIT: Basically you can add as many entries into the ViewState collection as you want. Sometimes it is wise to disable ViewState at all (EnableViewState property). In ASP.NET 4.0 you have more options to disable/enable ViewState by using the ViewStateMode property.
I set ASP.Net ViewState to off for a text box control, but the value for the name of the user is still there. Why is this so?
In a nutshell:
View state's purpose in life is simple: it's there to persist state across postbacks. (For an ASP.NET Web page, its state is the property values of the controls that make up its control hierarchy.) This begs the question, "What sort of state needs to be persisted?" To answer that question, let's start by looking at what state doesn't need to be persisted across postbacks. Recall that in the instantiation stage of the page life cycle, the control hierarchy is created and those properties that are specified in the declarative syntax are assigned. Since these declarative properties are automatically reassigned on each postback when the control hierarchy is constructed, there's no need to store these property values in the view state.
like balexandre already posted
ViewState cannot be modified by the browser, as the browser has no knowledge of what viewstate is. It's merely a snapshot of what was sent to the client and will be interrogated once the form is post back to the server.
Have a look at the following article to get a better understanding of what ViewState is
In a simple answer: Yes
But you should read all about View State as it's important to undertsand it and not thinking that things automagical work.
Understanding ASP.NET View State
When creating dynamic controls based on a data source of arbitrary and changing size, what is the official way to track exactly how many controls need to be rebuilt into the page's control collection after a Postback operation (i.e. on the server side during the ASP.NET page event lifecycle) specifically the point at which dynamic controls are supposed to be rebuilt? Where is the arity stored for retrieval and reconstruction usage?
By "official" I mean the Microsoft way of doing it. There exist hacks like Session storage, etc but I want to know the bonafide or at least Microsoft-recommended way. I've been unable to find a documentation page stating this information. Usually code samples work with a set of dynamic controls of known numbers. It's as if doing otherwise would be tougher.
Update: I'm not inquiring about user controls or static expression of declarative controls, but instead about dynamically injecting controls completely from code-behind, whether they be mine, 3rd-party or built-in ASP.NET controls.
This greatly depends on the problem at hand, and the type of controls you're recreating. Are they all simple text boxes or various different complex custom user controls. the main thing here is: if you want your dynamic control to regain state after a post-back, you have to re-create it in the Init phase of a page life-cycle.
Anyway. There's nothing like a Microsoft way or Microsoft recommended way basically. When you're dynamically adding several simple controls of the same type a hidden field with a count would do the trick, but when you have several complex controls other ways would have to be used. You could still hidden fields and save control's full type strings in them (ie. System.Web.UI.WebControls.TextBox) and re-instantiate them. But think of an even more complex example of putting various controls on different parts in the page... And initializing them to a specific state. That would be a bit more challenging. Hence no Microsoft way... The recommended way is to recreate in Init phase. And that's it.
Everything can be solved, but sometimes one took a wrong direction in the UI and things could be done easier using a different approach.
Additional explanation
This state-full technique of ViewState that Asp.net uses is considered the worse culprit with web developers in general. That's why Asp.net MVC developers think the new framework is bliss since its much more suited to the state-less HTTP protocol. Me being one of them. :D
What choices do I have for creating stateful dynamic content in an ASP.Net web site?
Here's my scenario. I have a site that has multiple, nested content regions. The top level are actions tied to a functional area Catalog, Subscriptions, Settings.
When you click on the functional action, I want to dynamically add content specific to that action. For example, when Catalog is clicked, I want to display a tree with the catalog folders & files, and a region to the right for details.
When a user clicks on the tree, I want a context sensitive details to load in the details region (like properties or options to manage the files).
I started with UserControls. They worked fine as long as I kept loading everything into the page, and never let one disappear. As soon as one disappeared, ViewState for the page blew up because the view state tree was invalid.
(I didn't want to keep loading stuff into my page because I don't want the responses to be too huge)
So, my next approach was to replace my dynamic regions with IFrames. Then instead of instantiating a UserControl, I would just change the source on my IFrame. Since the contents of the IFrames were independent pages I didn't run into any ViewState problems.
But, I'm concerned that IFrames might be a bad design choice, but don't fully understand why. The site is not public, so search engines aren't a concern.
So, finally to my question.
What are my options for this scenario? If I choose an Ajax Solution (jQuery), will I have to maintain my own ViewState? Are there any other considerations I should take into account?
Controls that are added dynamically do not persist in viewstate, and this is the reason that it doesn't matter if you use AJAX or iframes or whatever.
One possible work-around is to re-populate controls on postback. The problem with this, is the page life-cycle (simplified) is:
Initialize
LoadViewState
Load Postback Data
Call control Load events
Call Load event
Call control events
Control PreRender
PreRender
SaveViewState
Unload
What this means is the only place to re-add your dynamic controls is Initialize -- otherwise posted data (or viewstate information) is not loaded into that control. But often, because Viewstat/postback data isn't available yet in Initialize, your code doesn't have the information it needs to figure out which controls need to be added.
The only other work-around I've found in this situation is to use a 3rd party control called DynamicControlsPlaceholder. This works quite well, and persists the control information in viewstate.
In your particular case, it doesn't seem like there are that many choices/cases. Is it practical just to have all the different sets of controls in the page, and put them inside of asp:placeholder controls, and then just set one to visible, depending on what is selected?
Some other options:
Content only appears to be dynamic. You load enough controls on the page to handle anything and only actually show what you need. This saves a lot of hassle messing with view state and such, but means your page has a bigger footprint.
Add controls to the page dynamically. You've already been playing with this, so you've seen some of the issues here. Just remember that the place to create your dynamic controls for postbacks is in the Page_Init() event, and that if you want them to be stateful, you need to keep that state somewhere. I recommend a database.
you've got a number of different options, and yes, IFrames were a bad design choice.
The first option is the AJAX solution. And with that there's not really a viewstate scenario, it's just you're passing data back and forth with the webserver, building the UI on the fly as needed.
The next option is to dynamically add the controls you need for a given post, everytime. The way this would work, is that at the start of the page life cycle, you'd need to rebuild the page exactly as it was sent out the last time, and then dump out all the unneeded controls, and build just those that want.
A third option would be to use Master pages. Your top level content could be on the Master page itself, and have links to various pages within the website.
I'm sure given enough time, I could come up with more, but these 3 appeared just from reading your problem.
dynamic controls and viewstate don't mix well, as noted above - but that is a Good Thing, because even if they did the viewstate for a complex dynamic page would get so bloated that performance would diminish to nil
use Ajax [I like AJAX PRO because it is very simple to use] and manage the page state yourself [in session, database tables, or whatever works for your scenario]. This will be a bit more complicated to get going, but the results will be efficient and responsive: each page can update only what needs to change, and you won't be blowing a giant viewstate string back and forth all the time
If I have a simple piece of data to store (an integer or string for example) I might choose to store that in ViewState, or using a HiddenField control.
Why would I choose one over the other?
ViewState
Hard for the user to decode (thought not impossible), which might be desirable
HiddenField
Value can be used in JavaScript
Are there other pros and cons?
Not really, ViewState is actually stored in a hidden field so the only real difference is the encoding.
Unless you need to manipulate the value with JavaScript or you hope to turn off ViewState on this page altogether then I'd use ViewState. Mostly just because there are third party tools (like this one) which understand ViewState and which won't understand your custom hidden field.
From a maintainability point of view, I'd use ViewState. It's less code for you to write, which comes down to fewer points of failure in your software. It also means that any developers coming after you will have an easier time maintaining your solution.
If you're not entirely comfortable with that, write a property accessor on the page that acts as a facade to retrieve the value from the ViewState. Later, if you feel compelled to convert it to a hidden field, the accessor can handle that switch seemlessly for the rest of the code. Just be sure you document your reasons for doing so.
Viewstate is only good on the page you are on or posting back to. With a hidden field you can access the data on the next page you navigate to (as well as other data) by using PreviousPage method of the Page object like so:
string term = ((TextBox)Page.PreviousPage.FindControl("txtSearchTerm")).Text;
The ViewState is stored in the page itself so it increases the page size and it may cause performance issues.
Also we can configure the application to save the viewstate on server rather than on page itself which might protect from some security issues.
Jomit
The hidden field are invisible on page and their values can be viewed in view source but the value of view-state are encoded and are not readable.
The hidden field value are posted on next page. (Note: use server.transfer to get the value of hidden fields).