Introduction

ASP.NET ViewState is a great mechanism that simplifies the life of ASP.NET developers. But, as everybody knows, the .NET Framework saves the ViewState data as a hidden field on your ASPX page. If your page has only a few controls, this is not a problem. But, if your page has some Panels and/or some DataGrids, with the technique demonstrated on this article, you could reduce dramatically the load time of the page.

We will start our analysis thinking where the Framework needs to work with the data saved on the ViewState hidden field. The answer is: only on the server side. The system doesn't need to work with the ViewState data on the client side, so, if we start to save this data on the server instead of carrying all this from the server to the client and from the client to the server again, we will save a lot of time while loading our documents. You probably won't note the difference while loading the page on the same computer that the application is installed, but, test it using a dial-up connection and you will see what happens. You cold also see the the size of the source code generated with and without this technique.

This example consist of a class that inherits the System.Web.UI.Page, and overrides the methods SavePageStateToPersistenceMedium and LoadPageStateFromPersistenceMedium. These methods are responsible for saving and loading the ViewState used by the controls on a page. What we do is intercept the call to these methods and, using some simple custom config keys on the Web.Config, set how this class should work. It can save the ViewState on the server using two destinations: Session and Cache, and, has the ability to work as the original class, saving the ViewState data to the ASPX page.

If you already have a project and want to start using this technique, all that you need to do is add a reference to the class that accompanies this example and inherit your "code-behind files" from it instead of the System.Web.UI.Page, and add the Config information to your Web.Config.

To develop this technique, I read a lot of articles over the internet, but, one really "opened my mind" of how this implementation could be done and the benefits of it. See more information on the Points of Interest Section.

I included a demo project that you could download and use to test the implementation. Note that the demo project saves the ViewState to the session, which I think is the best place to store it.

Using the code

As I said, the implementation is very easy. So, let's start with my Class code, and after discussing it, let's see the configuration of the Web.Config file.

Now, let's see the method responsible for saving the ViewState data, called SavePageStateToPersistenceMedium. All that this method does is see if the ServerSideViewState on our Web.Config file is enabled (True). If no, the system will perform a normal ViewState save, storing it on the ASPX document. If yes, the system will check which is the ServerSideViewState method that you want to use: CACHE or SESSION. If you choose CACHE, the data will be stored on the cache and will expire after some time. If you choose SESSION, the data will be saved on the user session and will be discarded when the user session expires. When this option is used, the system automatically creates a DataTable that will be saved on the session and will hold all the ViewState data. The maximum number of ViewState data that could be held on the DataTable is defined by the Web.Config parameter ViewStateTableSize. The default value, 150, represents that the ViewState data of the last 150 postbacks will be available to the system. So, if the user clicks on the navigator's Back button 150 times (what is improbable to occur), the ViewState for that page will already be present to be used. This is a very good number...

And now, this is what we need to insert on our config file Web.Config:

<!-- application specific settings --><appSettings><!--ServerSideViewState: Defines if ViewState
will be saved on the Server: True|False--><addkey="ServerSideViewState"value="True"/><!--ViewStateStore: Defines where we'll save the ViewState: Cache|Session--><addkey="ViewStateStore"value="Session"/><!--ViewStateCacheFSSize: Define the maximum Number
of viewStates will be saved when ViewStateStore = Session --><addkey="ViewStateTableSize"value="150"/></appSettings>

Points of Interest

A lot of research was done to implement the login presented on this article. One of the most interesting sources is this. If you would like to know more about these techniques and see the result of some stress tests, follow the link.

Conclusion

ViewState really simplifies the development of ASP.NET applications, but due to increase in the page load time, some developers don't like to use it. With this technique, you could have all the advantages of using ViewState on your projects without worry about the size of the generated page source code.

Share

About the Author

Régis Daniel is currently living in Itaúna, MG, Brazil. He works with programming since 1999 and actualy works as IT Manager on a wholesaler company. He has experiency as Oracle DBA, and also worked as a PalmOS developer using CodeWarrior with C/C++.
Now a days he works on .NET Framework, developing solutions on Visual Basic.NET and ASP.NET. During his spare time, he likes reading books, watching movies and pratices some outdoor activities, like Trekking and Camping.

This is really not bad. A good example of thinking outside the box for once

However, using a DataTable and storing it into the session wasn't such a good idea. Every postback adds another record to this table (although up to a maximum). The viewstates don't get deleted this way. You really never need to store more than the current viewstate, so a table to store them is superfluous.

I've created a simple class that holds URL, sessionID and the viewstate and I store that directly into the session, using a constant key.

Hmmm, I am using this approach (slightly modified) with an AJAX updatable panel and not getting any issues unless I try to mess around with the back button too much in which case AJAX goes a bit nuts anyway.

So I suggest trying it out and seeing if you have the problem yourself.

When some of our users have been logged on for some time they get an error when the VsDataTable is set (in LoadPageStateFromPersistenceMedium):VsDataTable = Session("__VSDataTable")

It seems like the session has been cleared/removed.
I have tried to increase the timeouts we no luck.

1) The <sessionState> timeout in web.config is set to 70 minutes
2) The Session timeout in IIS 6 for the site is set to 70 minutes
3) The idle timeout for the worker processes in the application pool is set to 70 minutes

One point where it can be optimized is that it keeps a lot of unnecessary data in session. ViewState data ist only needed for the last postback and can be deleted right after it's usage. This data can pile up and become a real problem on sites with high traffic.

Here is my suggestion for more compact and better performing code. It works fine unless a frameset uses the same page in different frames at the same time (which is rather uncommon).

If (String.IsNullOrEmpty(sViewStateKey)) Then
Return MyBase.LoadPageStateFromPersistenceMedium()
End If

Return Session(sViewStateKey)

End Function

I can turn this functionality on per page by just setting the new base class property SaveViewstateInSession to true in the constructor of any derived pages.
If I wanted to I could turn this off for the whole site by having a web.config setting but I don't need that.

Also this approach doesn't worry about whether the SaveViewstateInSession isturned on or not in LoadPageStateFromPersistenceMedium; if there is a __VIEWSTATE_KEY hidden field it is going to try and retrieve it out of the current session.
If the __VIEWSTATE_KEY is not set then it will just default to the base class behaviour.

Ideally if this should be working, I presume that if in SavePageStateToPersistenceMedium I do nothing and dont save any viewstate and in LoadPageStateFromPersistenceMedium I return null, I still see webforms maintaining viewstate (just fine as ever). Just that it is not seen on the webform. Theoritically these methods (it seems) cant be used to suppress / override viewstate saving (just that its no more on the form).

To answer your question, if you do not override LoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium methods then base method implementation will set ViewState by default, due to which you could able to see all you objects set to it's state correctly. Try returning NULL from these methods, you will see what implication it creates.

Harshdeep Mehta
"Everything is possible, it just depends on how you play the game."

Others can blab all they want about how wrong it is to store ViewState in a Session, but I can see there are advantages of using this when ViewState is necessary and you want to reduce the file size sent to the client's browser.

Anyway, great article.
I might find a page or two where I want to implement this.

This seems not working in SQL server session mode for me. It works well on inproc mode. I am getting the follwing error.

Specified cast is not valid.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

hi, thanks for the quick response. i type casted the Dbrow(Vsdata") into triplet and logged it's first, second and third values. the first parameter has some value and the other 2 gave object not set error. my environment is a multi clustered one with sqlserver session storage. do i need any special access rights on the webserver. i donot have admin previledge on the machine. any clue about solution to my problem?

This is a strange problem. I don't think that you need to have a special right on the webserver, neither on the sqlserver...

Try to disable the ServerViewState feature on your Web.Config file. This will make the system saves the view state on the page body again. Then, log the content of the triplets while the viewstate is being saved and load.

If the error occurs again, try to inherit your page class from System.Web.UI.Page and rerun the test. If the error persists, we need to analyze the problem closer.

Hi,
I did a little bit testing and found that the Triplet class is not serializable. When we use sql server session storage mode of web server then all the contents we put in the session needs to be serializable. The serialise/deserialise the viewstate we need to use the Losformatter class. The problem is - the time it takes to deserialise the viewstate is not acceptable. We loose our performance improvement for large viewstates.

But i am not sure how it worked in your SQL server session storage mode without the use of serialization/deserialization using losformatter class!! Did you tested the SQLserver session storage mode after you implemented it. One mistake which i did while implementing was i forgot to change the inproc entry in web.config, although i changed the machine.config. Hence for a few days i was really using inproc while i was thinking of using SQL server session storage.