ControlState vs ViewState

Created: January 3, 2015 Tagged As: ASP.net, C#, Web Forms Share:

Writing custom ASP.net server controls scares most ASP.net coders. That is unfortunate as a custom server control is a perfect example of object-oriented design - a component that loosely couples with its owner and renders HTML output dynamically based on property settings and (usually) data.

One of the biggest issues with ASP.net since its inception has been ViewState. While great in concept, in practice, it does, at best, bloat a web page to an almost unusable size if not managed properly. For this reason, I am a big fan of disabling ViewState everywhere and only enabling it when totally necessary.

But what does disabling ViewState really mean under the hood?

ViewState Within a Control

Virtually every property you set within a server control is stored in a dictionary called a StateBag whose alias within the control is ViewState. When you set the Text of a Label control, that string is stored in the ViewState statebag.

If the ViewStateMode property on the control is set to Enabled, then everything within the ViewState dictionary is serialized into a hidden field on the ASP.net page called __VIEWSTATE. For a page consisting of a couple of controls, this may not be a problem, but as the control count grows so does the view state size.

Now if the ViewState mode is set to Disabled, that information is NOT sent to the browser. So why wouldn't you always disable ViewState?

By NOT sending the information to the browser, in our example, the label's Text property will be reset to its default value (i.e., what we've typed into our ASP.net web code) on each postback. For many controls this is not a problem - like for our label, why would we need to keep its value between postbacks if it never changes?

For more complex controls like ListView, GridView, and the like, the situation gets more complicated and this is where ControlState comes in.

ControlState

Now consider the case of a control that needs data to be persisted between postbacks even if ViewState is disabled. ControlState was invented for this reason. When information is put into ControlState, it will be serialized into the __VIEWSTATE field no matter what. Consider this example:

 

[ToolboxData("<{0}:MyLabel runat=server></{0}:MyLabel>")]
public class MyLabel : System.Web.UI.WebControls.Label
{ 
   public int PostbackCount
   {
      get; 
      set; 
   }

   protected override void OnInit(EventArgs e)
   {
      Page.RegisterRequiresControlState(this);
      base.OnInit(e);
      if (this.Page.IsPostback)
         this.PostbackCount++;
   }

   protected override void LoadControlState(object savedState)
   {
      if (savedState is Pair) 
      {
         Pair p = (Pair)savedState; 
         base.LoadControlState(p.First); 
         this.PostbackCount=(int)p.Second;
      }
      else
         base.LoadControlState(savedState);
   }

   protected override object SaveControlState()
   {
      object o = base.SaveControlState();
      return new Pair(o, this.PostbackCount);
   }
} 

In this case, the PostbackCount property will be persisted between postbacks regardless of the ViewState setting.

So why is ControlState used in this example? Because the control would break and be completely useless without it. If we were to just store the value in ViewState, then the control would behave as expected until ViewState is disabled.

Could we create a hidden field and store our value in it or use some other mechanism? Quite possibly, but ControlState is already built-in and other controls are using it, so I will argue that it is actually more efficient.

Conclusion

We have learned that we always want to use ViewState judiciously to keep our web forms efficient. And as a control developer, we have learned that there is a way to force information into the __VIEWSTATE hidden field no matter what.