My previous post on view state in ASP.NET 2.0 talked a bit about the encoding improvements, and as promised I'll talk a bit about the new control state mechanism in this entry. Before I do, you may be interested in a post on some of the view state improvements posted by Nikhil Kothari where he talks about the encoding changes and briefly mentions control state as well.
Control state addresses one of the most frustrating aspects of view state in ASP.NET today - the fact that you have to leave it enabled for some controls to work at all. This turns up most evidently in the DataGrid which requires view state to be enabled if you want to add handlers to any of its server-side events (like EditCommand, PageIndexChanged, etc.). This is especially frustrating because the view state stores all of the data that is bound to the grid, and if you're not relying on that data being transmitted across requests, you incur the (potentially significant) increase in response size for what feels like no good reason.
Control state is essentially another state repository whose contents is propagated much like view state, but the purpose of the control state repository is to cache data necessary for a control to properly function. To put it another way, behavioral state for a control should be kept in control state, and UI state (its contents) should be kept in view state. Thus in the new GridView class, you can completely disable view state, and the pagination and editing events still fire as expected.
After I first learned about control state (from Nikhil actually, at a tech preview) I went looking for a hidden __CONTROLSTATE field. I quickly found out, however, that control state is actually stored in the __VIEWSTATE hidden field along with the rest of the view state. From what I can tell, it is always stored as the last node in the view state tree which is an instance of HybridDictionary (when there is any control state). If you are interested in exploring control state (and view state for that matter) I have an updated version of my ViewState decoder available here (compiled against the May preview release of VS.NET 2005) that shows both view state and control state on any given page.
As a control developer, you should be very careful about how you use control state, because there is no way for users to disable it. If you start throwing lots of state into control state, you will quickly make enemies of most of your clients :) It should only contain state that is necessary for the proper functioning of your control. The example of the GridView is a good one to use as a model - it stores a number of indices that it uses to determine whether events should fire on the server (EditIndex, SelectedIndex, PageIndex, SortDirection, and SortExpression). Note that all of these items are simple integers (or strings) and will never explode in size relative to the data bound to the control.
To actually write to control state, you have to override a couple of virtual functions and enable it in the containing page. There is not a corresponding ControlState property bag - and I suspect the reason is the ASP.NET team members did not want to make it too easy to add state to the control state collection :)
Here's a control that writes a piece of state to the control state collection:
public class SampleControl : Control
{
int _idx = 0;
protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
protected override void LoadControlState(
object savedState)
{
object[] rgState = (object[])savedState;
base.LoadControlState(rgState[0]);
_idx = (int)rgState[1];
}
protected override object SaveControlState()
{
object[] rgState = new object[2];
rgState[0] = base.SaveControlState();
rgState[1] = _idx;
return rgState;
}
// ...
}
Note the call to RegisterRequiresControlState in the OnInit method - this is required to tell the containing page that your control will be storing control state. The two virtual functions, LoadControlState and SaveControlState are your two hook points for loading and saving the control state (much like the analagous view state methods which you may have used before).
If you're building controls today, it might even be worth mimicking control state by adding your own hidden field to your control rendering and storing your behavioral state there, instead of just breaking when a client disables it (with the best of intentions).
Posted
Jul 01 2004, 12:02 PM
by
fritz-onion