SP.NET provides a couple of page-level state persistence mechanisms in ViewState and the new ControlState.
While both mechanisms work, they both have some limitations in that they are not deterministic for the application developerViewState can be turned off and can be very bulky, and ControlState can be set only from within a control implementation. In this article I'll show another, more flexible state mechanism using a PreservePropertyControl that allows automatic persistence and restoration of field values automatically without requiring ViewState.
ASP.NET 1.x provides ViewState and ASP.NET 2.0 adds ControlState. Both mechanisms provide the ability to persist page-specific state across a single page postback by embedding the state data into the page as a hidden form variable called __VIEWSTATE
. Both work for specific scenarios but I also think that both have serious limitations that make them inappropriate in some scenarios and more difficult to use than they have to be.
Wouldn't it be nice to have a built-in mechanism to declaratively store a property value of a control or the page and have it automatically restored when the page is posted back?
Sounds a lot like ViewState, right? But ViewState is not declarative and not easily controlled. If you turn off ViewState, as I do whenever I can, you immediately lose the ability to track any values in ViewState at all. Controls stop tracking, and you can no longer use the ViewState collection to store values from your application code. Turn ViewState on and you end up picking up all changed values of all controls that have changed non-postback values and that have ViewState enabled. In other words it's an all-or-nothing approach, even though you often want to persist only one or two values of a page.
I ran into this a couple of days ago when I was dealing with a complex DataGrid. The DataGrid is set up with ViewState off. There are many actions, like Delete
, Update Status
, etc., that fire postbacks from each row. There's also paging and sorting. Without ViewState it gets real messy trying to get the DataGrid to keep track of the CurrentPageIndex
Wouldn't it be nice if you could do something like this?
|ViewState is an all or nothing mechanism. Once enabled it tracks all changes to controls.|
And you're done? You don't need to use ViewState. You can choose to have a single value persisted instead of all the DataGrid data. The same would go for persisting properties of any other control like the ForeColor
of a button:
This would work without ViewState enabled and you'd stick this code at the beginning of Page_Load()
or other code that runs on any request. ASP.NET would then automatically write out the value at the end of the request and restore it when the page loads again on a postback. Now that's a page-level state mechanism that's easy to use and flexible.
Controls could internally use the same mechanism. Controls could persist their state to this same statebag deterministically similar to the way ControlState does in ASP.NET 2.0. ControlState is new in ASP.NET 2.0, and I'll talk more about it later in this article.
Unfortunately, this approach of using a method on the Control class assumes a change to the Control class by adding a PreserveProperty
method, which would then be available on all controls automatically. But making changes to the Control class is an option only if you are Microsoft, as you can't extend Control and have other stock controls inherit from a modified Control class.
The next best solution is to build an external control that you can drop onto a page or add to a control to provide this same functionality. In this article, I'll show you how to build such an extender control.