Control state in ASP.NET 2.0

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
Filed under:

Comments

Onion Blog wrote Interlude - caching declarative data sources
on 04-07-2005 5:49 AM
Josh wrote re: Control state in ASP.NET 2.0
on 04-13-2005 5:56 AM
I noticed that the OnInit of a control that is placed into a WebPartZone (and therefore turned into a GenericWebPart) is not called until the page enters the PreRender state. This means that other controls on the form can edit the properties of the WebPart control before it loads its ControlState. The properties are then overwritten with their previous values.

Does this seem right to you? This isn't a problem if the control is not a WebPart, because the control's OnInit gets called with the rest of the page's OnInit's.
Fritz Onion wrote re: Control state in ASP.NET 2.0
on 04-14-2005 1:48 PM
Hmm, I hadn't noticed that potential problem - it does sound troublesome. I'll take closer look at possible solutions when I get the chance.
Joe wrote re: Control state in ASP.NET 2.0
on 05-16-2005 1:50 PM
Josh, this is a general control framework issue that is not specific to Webparts.

I think if you do not access a control then you're right: it is not created or initialized until PreRender. However, if you try to change one of its properties, this would force creation and initialization at that time.

If you noticed the opposite, please could you contact me and provide a small repro / sample code? Thanks! - Joe
Coding Horror wrote Wrangling ASP.NET Viewstate
on 10-12-2005 11:39 PM
Inspired by Scott Hanselman's recent post on ASP.NET viewstate wrangling, here's a roundup of tips for dealing with that ornery viewstate stuff. The first rule of thumb, of course, is to turn it off whenever you can. But sometimes...
Wimdows.NET wrote ViewState, CheckBox, ControlState...errr...
on 08-24-2006 7:12 AM
J. Michael Palermo writes about the CheckBox in ASP.NET maintaining its state regardless of the EnableViewState
Ram Marappan wrote asp .net view state - developer notes
on 09-07-2006 8:12 AM
 

ViewState is of type StateBag. StateBag is like adictionary and implments ‘IStateManager’ ...
Community Blogs wrote Lightweight Invisible CAPTCHA Validator Control
on 09-26-2006 3:10 AM
Not too long ago I wrote about using heuristics to fight comment spam. A little later I pointed to the
Creative Minds wrote Lightweight Invisible CAPTCHA Validator Control
on 09-26-2006 4:55 AM
Lightweight Invisible CAPTCHA Validator Control
Ancora Imparo wrote ASP.Net Quick Tips - State Management
on 02-27-2007 7:23 AM
The web is inheritently stateless, however, ASP.Net provides you with a very comprehensive list of options
Kris - TECH wrote ASP.Net Quick Tips - State Management
on 03-16-2007 5:41 AM
Filed under: aspnet , asp.net tips by Scott Watermasysk on February 27, 2007 The web is inheritently
PRAVEEN wrote how to generate autouser id
on 03-24-2008 4:26 AM
my id types be

A000x001

A001Y002

A002Y003
Web Designer wrote re: Control state in ASP.NET 2.0
on 04-28-2008 12:31 PM
Do you have this code in vb.net?
dev wrote re: Control state in ASP.NET 2.0
on 05-07-2008 2:33 PM
Your EXE didn't work for me. I get the following error message in red at the bottom of the window after clicking Decode, no matter what page I load:

"There was an error decoding the ViewState string: The serialized data is invalid."

Add a Comment

(required)  
(optional)
(required)  
Remember Me?