Search code examples
c#asp.netviewstateweb-controls

When is it acceptable to override a feature associated with ViewState and make it use ControlState?


ControlState vs ViewState

I am working with a RadListBox. RadListBox has the following property which is set to True by default: PersistClientChanges

The functionality of this property is dependent on ViewState. That is, when a change is made client-side, the changes are stored into the ViewState model for the control -- and then during next postback the ViewState is parsed, the changes 're-run' and applied to the control server-side.

Unfortunately, I do not have ViewState enabled on my page, and I'm not really trying to have it enabled, either. That being said, I want this functionality. So, I am looking at my other options.

The MSDN documentation states "Use control state only for small amounts of critical data that are essential for the control across postbacks. Do not use control state as an alternative to view state."

And I am wondering:

  • What counts as a small amount of critical data? A bool? A small list of items? Less than 10000 data points??
  • What kind of gotchas should I be aware of? Is this a dumb path for me to following? Etc..

Just any other information on using ControlState properly would be nice. Thanks.


Solution

  • First i must admit that i've never used ControlState to persist values across postbacks. But control developers who create Controls that are used by other developers might want to use it to ensure functionality even if ViewState is disabled. Otherwise disabling would result in incorret behaviour or errors that are not obvious.

    So in my opinion you would use ControlState if you would normally use ViewState but you must ensure that the control also works when ViewState is disabled. In this case the sentence "Do not use control state as an alternative to view state" would be wrong, because you should use ViewState as well only for small amounts of data that must be persisted across postbacks.

    An example to clarify what i mean:

    Consider you want to create a custom control that inherits GridView. You can store the data in ViewState to maintain values across postbacks. You should allow to disable the ViewState on your control without any problems, you should not rely on the fact that it's enabled, because developers who are using your control might want to reduce network traffic. But you could provide other properties that are stored in ControlState like SortDirection, PageIndex, DeleteButtonText etc. that you think are important and are single values, therefor less resource intensive than storing all GridViewRows.

    Edit: According to your actual problem:

    You could enable ViewState for some controls and disable it for others, but you cannot disable it for whole page and enable it for child-controls in this page.

    If you set turn page's ViewState off, then there is no way for you to enable ViewState for specific components. This is because ViewState is serialzed recursively, so when if the Page is not allowing ViewState, it will not serialize the ViewState for any of it's child controls. If you don't want to explicitly turn ViewState off on individual controls, but want to keep some controls ViewState aware, the best way would be writing a small utility method which turns ViewState off for all controls (using recursion or otherwise). Then enable ViewState for the controls that you would like to enable ViewState for. Alternatively, a middle ground and less forceful way may possible if controls are groups inside other container controls (such as Panel). You can disable ViewState for all controls inside a Panel by disabling ViewState of the Panel.

    Enable ViewState for few controls and disable for others/page

    Edit: Here is an extension to enable/disable ViewState for all child-controls(VB.NET)

    <System.Runtime.CompilerServices.Extension()> _
    Public Sub EnableChildViewState(ByVal parentControl As System.Web.UI.Control, enable as Boolean) 
        If parentControl.HasControls Then
            For Each c As System.Web.UI.Control In parentControl.Controls
                c.EnableViewState = enable 
                EnableChildViewState(c, enable)
            Next
        End If
    End Sub
    

    You can call it:

    Page.EnableChildViewState(False)
    MyControl.EnableViewState = True