CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

Do you really need this Viewstate thing ?

I spent the last days mainly on the ViewState. Read a lot about it and tried even more things. Quite interesting, often very frustrating, but worth a roundup which leads to a positive conclusion. Lets' start with a small recap. The viewstate of an asp.net webpage is the vehicle in which the state of a web page travels. When the user posts a page back to the server the server will return a new copy of the webpage in which the state of all controls, like the text in a textbox or the contents of a datagrid, is preserved. This state is encoded in a hidden form field on the page named __ViewState, you will see it when you do a view source in your browser. This field is included in the response coming from the server but also in the request posted back to the server. With the state (-changes) stored in the html page the webbrowser plays an important role in state mangement.

Almost every property (-change) of a webcontrol is stored in this viewstate. One of my apps has pages with many row datalists, the size of the request alone sometimes exceeded 100 K ! Which resulted in a not so snappy performance and was the main reason for my investigations. My first attempt was to completely get rid of the viewstate. The System.Web.UI.Page has two methods which deal with its persistence. Both are virtual an can be overridden.

protected override void SavePageStateToPersistenceMedium(object vs)
{

    base.SavePageStateToPersistenceMedium(vs);

}

protected override object LoadPageStateFromPersistenceMedium()
{

    return base.LoadPageStateFromPersistenceMedium();

}

The default base implementation of the first method stores the serialized viewstate in the hidden __viewstate field on the page and the second retrieves the viewstate from the page. On the web I found several people who had overridden this method to store the viewstate in the session instead of the page. The viewstate data then stays on the server. Some solutions were pretty straightforward, they used one session variable to store every viewstate in the session. Which could work as long as the session has only one page open. Another implementation recycled an array of multiple states and another one even maintained a dynamic collection of sessions vars, one for every url. Especially the latter will lead to gigantic scaling problems. Just imagine a user having an all day session visiting a couple of hundreds of pages. It only takes a couple of those to cripple any web server. I am not giving you any links to these sources, besides their theoretical issues they just do not work. I also use the viewstate in my code to store some of my own stuff. Maybe that is the reason, maybe something else, but I experienced that every viewstate given back by the session was screwed up.

Another solution to get rid of the viewstate hog is to disable it. Every control (including a page) has an EnableViewState property. Default this is set to true. The most pages of my application contain a DataList component with database data. This dnj article describes the idea. In the article and its precursor on the DataGrid I already mentioned some thoughts on the viewstate. As the data in the list are re-read on every roundtrip they do not have to be persisted in the viewstate. The bad thing is that setting the list's EnableViewState property to false screws up the working of the EditItemIndex and SelectedItemIndex property. You can try to handle those properties in your own code. The DataGrid  and the DataList components have an SelectedIndexChanged event which will get fired on an index change and they do receive the correct new index in the event's arguments. But the bad thing is that these events get fired too late. In my article was an overview of the events on a page roundtrip, the problem is that the components only render as desired when the index is set in the initialization events, like Init. The SelectedIndexChanged event fires later, setting the SelectedIndex property in there will result in a correct rendering of your component on the next roundtrip. Not really a desired behaviour. The EnableViewState property of a DataList or DataGrid just has to be enabled for the controls to be usable.

The good thing with the EnableViewState property is that it can be disabled on almost all other controls. The data is presented in (data bound) text-boxes and labels in the templates of the list and is reloaded in the DataBind of every roundtrip, so they do not need the viewstate. For linkbuttons and normal buttons it is almost ridiculous to have a viewstate, except when you want their appearance to change over roundtrips. The only controls which really do make a sensible use of the viewstate are (dropdown-)listboxes and treeviews. If you disable their viewstate you will not be able to see which item was selected by the user. It would make sense to get  the contents of the list out of the viewstate as that will not often change over roundtrips, more on that later. After a lot of property editing and testing I was disable the viewstate for most of the components. The result was great. I tested the viewstate size by looking at the size of the request :

Response.Write(string.Format("

RequestSize {0} Bytes

", Request.TotalBytes));

On some pages it resulted in a reduction of 90% in the size of the request and 50% in the size of the response. Without the loss of any functionality. The next question is how the app will behave on the intranet of my customer.

This ViewState matter has also been adressed in Whidbey. In there a control has besides its viewstate a controlstate property. The controlstate is used to persist those properties which are essential to a component. The controlstate cannot be disabled. The ViewState is still there as well. But after all, the only real problem is that it is enabled by default.

Blog on,

Peter



Comments

Peter van Ooijen said:

It does propagate. When it comes to the viewstate a page is a control like any other. So disabling the viewstate on the webform will disable the viewstate for all controls on the page.
# January 22, 2004 1:39 AM

Allen Guest said:

A little bit of a dated comment, but why don't you just rebind in the OnPreRender event? All of the events including SelectedIndexChanged would have fired and you would have up-to-date SelectedIndex property even without the EnableViewState property set?
# April 26, 2004 3:42 PM

Peter van Ooijen said:

hi Allen, never mind about a late comment. E-mail notification works just fine. Good to notice is it still read.

When you disable the viewstate SelectIndexChanged will never fire as the property always has its design time set value.

In my grids and list I usualy perform the bind in the prerender event. Not a rebind, the pageload is usualy to early to bind. Other events might change the data I'm binding to.
# April 26, 2004 3:53 PM

Vikas Sharma said:

Could u plz let me know i have several server controls on my page.Is there any means to reducetheviewstate size when we review itat browser

If it so could u plz asssit me at my id itsvikas1@rediffmail.com
# September 6, 2004 6:04 AM

Peter van 0oijen said:

Every control has an enableviewstate property. Set this to false for al controls whose state does not change over roundtrips or whose state is stored elsewhere. Fi : a label or button usually does not change.
# September 6, 2004 9:40 AM

Peter's Gekko said:

Viewstate (hog) and the datagrid
# December 15, 2004 2:25 AM

Simon Littlehales said:

Hi Peter, Great article!
I've been scratching my head for months trying to work out why I could never use the SelectedIndexChanged event when i disabled the viewstate!
Did you ever find an (easyish!) way around this?
# December 15, 2004 5:59 AM

Frans Nagel said:

I found that disabling the viewstate per DataGridItem works well. You can still get to the griditem in a decent way. And it greatly reduces the view state
# December 29, 2004 1:16 AM

Peter van Ooijen said:

I'm sorry Frans but I don not understand this. The datagrid as a whole has an enableviewstate property. The individual items do not. Or am I missing something ?
# December 30, 2004 2:59 AM

dejawoo said:

hi Peter. I have just some issues that could not make well understood. I have read from many sources that viewstate mainly used to just make a comparison among the current and previous postbacks and make LoadDataPost for the all controls which are implemented the particular interface. Thus everything just works as in old days with Request.Form. All control statements modified at client side goes to server with Request.Form() to the server including the Viewstate hidden field. then it s kind a extracted and compared with the values in arrived viewstate if it s need to be updated it s updated... am I right up to this point? and there was some articles those were emphasizing on textbox. that it s kind a textbox doesnot use a viewstate.. and the last thing I have a dropdownlist, items are defined in .aspx page. But the weird thing that even the viewstate disabled I get the selected value after postback.. could you give some explanation to these issues. thanx alot. could you make me informed if it s possible deja_woo@hotmail.com My great prethanx. Sharing is adorable.
# July 8, 2005 10:35 PM

pvanooijen said:

hi, the viewstate is intended to maintain values over roundtrips. The selectedvalue of a dropdownlist is the value selected in the most recent post.

The viewstate is supposed to store changes, like the code filling a dropdownlist with items at runtime from a DB. Fill on the first trip and maintain the values over roundtrips.

The viewstate is implemented as a hidden form var, just to make storing it easy.

My main problem with the viewstate is that is add a lot of size to your page. And when the contents over the roundtrips does not change it can be pretty nasty.

I've an article coming up to demonstrate this. Coming soon.
# July 11, 2005 8:35 AM

jeffnoll said:

Is there a way with drop down lists to not have the Items stored in ViewState? I've inherited the ddl and extended it to work with a configurator tool. Because of the functionality that I need I can't disable ViewState complete on the controls. However, I have a page with like 50+ ddls initially, and the page size is over 160K. On each select change the page gets resubmitted to the configurator and all the ddl are recalculated and popuated, so ths isn't an issue.

So is there a way to keep view state on, but just not store the Items?

Thanks,
# July 22, 2005 8:50 AM

pvanooijen said:

You can disable the viewsate for the dropdownlist and re-populate the items on every roundtrip. But by repopulating you will lose the selectedindex of the list. Takes some caution, but can be done.
# July 23, 2005 5:57 AM

Jethro said:

there's a way to get the selectedvalue of a using a dropdown without viewstate

u can use the Request.Form variables which contains the values of forms controls which are posted. The key of the forms variables are the UniqueId of the Control.

when postback, on Page_Load

string SelectedValue = this.Request.Form[myDropDownList.UniqueID].ToString();

Hope it can help

# August 4, 2005 7:06 PM

Alex said:

THANK YOU JETHRO

Been pulling my hair out for about 5 hours about this... I refused to resort to viewstate... Now it works :D
# April 9, 2006 11:30 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

Our Sponsors

This Blog

Syndication

News