Most people who have worked with ASP.NET web forms know about view state; they may have both benefited from and cursed it, since it allows simple things to be done very easily but also as easily doing very stupid things, like filling up an HTML page with several megabytes of data which have to be submitted on each postback.
What some people won’t know is that the way the view state is maintained is extensible and based on a provider model. Besides the default way of storing view state in an hidden field, ASP.NET includes another implementation of the provider which allows state to be stored in the session, thus keeping it out (but for a small part) of the HTML. The abstract base provider class is PageStatePersister and the two included implementations are HiddenFieldPageStatePersister and SessionPageStatePersister.
So, what keeps you from storing everything in the session? It seems like an easy choice… there are some drawbacks, however:
- All browser tabs share the same session, so care must be taken if the same page is open on two tabs, because changes to the session made in one page will affect the other, since the data is shared between them;
- Because data is kept indefinitely at the session, either until the session expires – which may never happen – or it is explicitly removed from it, memory will grow up enormously.
So I decided to go for another option: storing data on the cache, with an expiration value. This should be a reasonable default, after which, data would be gone, if no postback happens in the mean time. I made it configurable: a global default timeout may be specified on the Web.config file or specifically for a web Page in its Items collection. It is using sliding expiration, so each time the cache is touched is will keep it alive for an equal period of time.
One problem is how to identify uniquely a page instance, so that its view state is local to it only, but I have already solved some time ago.
OK, so let’s see the code:
Finally, how to use this. There are two options:
- You can override each page class’ PageStatePersister property:
- Or you can apply the persister through a control adapter, which is less intrusive, in two easy steps:
- Create a custom PageAdapter:
- Add a file named, for example, Default.browser, to the App_Browsers folder:
Of course, you can target page types other than the base Page itself by changing the value on the controlType attribute.
You can change the default cache timeout from 10 minutes to something else, globally in the Web.config:
Or by code, page by page:As always, hope this is useful, and looking forward to hearing your feedback!