13

When I disable ViewState for the page. It does not allow any other control to use ViewState .. even if I set EnableViewState="true" for that particular control ..

is it possible to enable ViewState for a control when ViewState is disabled for the page itself?

if not how can disable viewstate for controls on page except for few without specifying EnableViewState="false" explicitly .. typing the same into so many controls is hectic ..

Zuhaib
  • 1,420
  • 3
  • 18
  • 34

8 Answers8

22

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.

In answer to your question, 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.

Samuel Kim
  • 3,723
  • 2
  • 23
  • 18
  • Would the same concept work on a Placeholder? That'd get around the problem of having excess HTML tags generated. – Aaron Powell Oct 09 '08 at 10:47
  • Placeholder is only beneficial in text contents. If you have a calendar control and don't want to have ViewState, you don't want to use Placeholder and write the calendar HTML. – Samuel Kim Oct 12 '08 at 12:20
  • Its certainly and option, but turning off viewstate for the container would turn off viewstate for all child controls including lables. – Zuhaib Dec 05 '09 at 04:49
  • 4
    In .NET 4, you can turn ViewState off, but if you set **ViewStateMode=Enabled** for a control, it will allow that control to keep ViewState even if the page has it disabled http://msdn.microsoft.com/en-us/library/vstudio/system.web.ui.control.viewstatemode%28v=vs.100%29.aspx – dgarbacz Dec 18 '12 at 15:11
6

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.it's child controls.

With the advent of ASP.NET 4 we have a new property called ViewStateMode that can be used to enable view state for an individual control even if view state is disabled for the page.

To make use of this new property you can either create a base page class that sets the ViewStateMode to Disabled or create a PageAdapter that does the same thing. There is no viewStateMode property in the web.config.

Here's the code for the page adapter:

using System.Web.UI;
using System.Web.UI.Adapters;

namespace Playground.Web.UI.Adapters
{
    public class PageAdapter: System.Web.UI.Adapters.PageAdapter
    {
        protected override void OnLoad(EventArgs e)
        {
            ViewStateMode = ViewStateMode.Disabled;
            base.OnLoad(e);
        }
    }
}

and here's the code for the browser file:

<browser refID="default">
    <controladapters>
        <adapter controlType="System.Web.UI.Page" adapterType="Playground.Web.UI.Adapters.PageAdapter" />
    </controladapters>
</browser>
Georgios Politis
  • 2,610
  • 3
  • 19
  • 10
2

With .NET 4.0 you can also define the Control Adapters

namespace BB.Common.UI.Adapters
{
    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class DisableViewStateControl : System.Web.UI.Adapters.ControlAdapter
    {
        protected override void OnInit(EventArgs e)
        {
            if (Control.ViewStateMode == ViewStateMode.Inherit)
                Control.ViewStateMode = ViewStateMode.Disabled;
            base.OnInit(e);
        }
    }
}

In above code, the ViewState mode is disabled when it is inherited. Add the following line in Browser settings file.

<browsers>
  <browser refID="Default" >
    <controlAdapters>
      <adapter
          controlType="System.Web.UI.WebControls.Label"
          adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
      <adapter
         controlType="System.Web.UI.WebControls.HyperLink"
         adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
      <adapter
         controlType="System.Web.UI.WebControls.ImageButton"
         adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
      <adapter
          controlType="System.Web.UI.WebControls.Button"
          adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
    <adapter
          controlType="System.Web.UI.WebControls.TextBox"
          adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
      <adapter
          controlType="System.Web.UI.WebControls.CheckBox"
          adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" /> 
      <adapter
          controlType="System.Web.UI.WebControls.HiddenField"
          adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" /> 
    </controlAdapters>
  </browser>
</browsers>

This way you can have more granular cotnrol over viewstate for each single control throughuout the application. And where you need control to have viewstate just enable it in code. That's it.

2

The simplest solution is:

<%@ Page Language="C#" EnableViewState="true" ViewStateMode="Disabled" %>

and wherever you want to enable viewstate:

<asp:yourcontrol EnableViewState="true" ViewStateMode="Enabled">

All credits reserved to Shredder's answer on this post

Community
  • 1
  • 1
BornToCode
  • 9,495
  • 9
  • 66
  • 83
  • EnableViewState="true" isn't *really* needed as it is default. ViewStateMode is evaluated as the following. if "Disabled", the EnableViewState property is ignored for that control. The code above basically ignores ViewState for the page, and uses the existing value for the control. Its an important distinction if you ever need to programmatically toggle those behaviors – KevinDeus Aug 10 '12 at 22:01
2

Here's some code which expands on @Samuel Kim's concept of having a way to disable ViewState on all but certain controls (btw, it uses .NET 3.5):

List<string> allowedControls = new List<string> { "Control1", "Control3" };
IEnumerable<Control> controlsWithoutViewState = Page.Controls.Where(c => !allowedControls.Contains(c.ID));
foreach(Control c controlsWithoutViewState){
  if(c is WebControl) ((WebControl)c).EnableViewState = false;
}

The only thing I'm not 100% sure on (and I don't have my VM running) is whether Page.Controls needs to be cast or not, if so just have this instead:

IEnumerable<Control> controlsWithoutViewState = Page.Controls.Cast<Control>().Where(c => !allowedControls.Contains(c.ID));

The above is only a quick concept of what to do, it doesn't take into account nested controls where you may want 1 with and 1 without ViewState, but it wouldn't be hard to make a recusive function to handle it.

Aaron Powell
  • 24,927
  • 18
  • 98
  • 150
0

I'm curious to see if Samuel's approach works. If you try it please post your result.

I'm not saying Samuel's wrong, I'd just be curious.

The reason I'm curious is because since viewstate is serialized recursively (as Samuel mentioned) if you had one control with viewstate enabled that was a child of a control with viewstate disabled, then the child control wouldn't have viewstate because the recursive serialization would skip over it entirely at the parent level. This would specifically be troubling if you have built your own user controls that would naturally contain a lot of child controls.

Another solution would be to use Samuel's utility method approach but instead of disabling everything, just disable it for controls like Label, Literal, etc that do not have children...or if they do have children it's ok if the children have viewstate disabled.

You would naturally want to avoid disabling the viewstate of Panels and Placeholders for the reason I stated above.

Edit:

Public Shared Sub DisableViewState(ByVal cntrl As Control)
    If TypeOf cntrl Is Label Then
        cntrl.EnableViewState = False
    ElseIf TypeOf cntrl Is Literal Then
        cntrl.EnableViewState = False
    ElseIf TypeOf cntrl Is Button Then
        cntrl.EnableViewState = False
    Else
        If cntrl.Controls IsNot Nothing Then
            For Each subControl As Control In cntrl.Controls
                DisableViewState(subControl)
            Next
        End If
    End If
End Sub
Adam
  • 3,063
  • 5
  • 35
  • 49
0

You can also subclass the built-in controls, and in your subclass set the EnableViewState property to false.

Mike Cole
  • 14,474
  • 28
  • 114
  • 194
0

You could also inherit from a BasePage. On the BasePage disable ViewState.

/// <summary>
/// All pages inherit this page
/// </summary>
public class BasePage : System.Web.UI.Page {

    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
    }

    public bool ViewStateEnabled {
        get {
            return Page.EnableViewState;
        }
        set {
            Page.EnableViewState = value;
        }
    }

    public BasePage() {
        // Disable ViewState By Default
        ViewStateEnabled = false;
    }
}

In each page that you want ViewState Enabled, you do the following in Page_Load:

public partial class Products_Default : BasePage {
    protected void Page_Load(object sender, EventArgs e) {
        this.ViewStateEnabled = true;
    }
}

This should enable ViewState just for that Page (assuming it's ON in the MasterPage). Note: You will need to individually set each control's ViewState on that Page.

Armstrongest
  • 15,181
  • 13
  • 67
  • 106