c# - valido - Habilite ViewState para algunos controles y deshabilite para otros/página
viewstate como funciona (8)
Si desactiva ViewState de la página de turno, entonces no hay forma de que habilite ViewState para componentes específicos. Esto se debe a que ViewState se serializa recursivamente, por lo que cuando la página no permite ViewState, no serializará ViewState para ninguno de sus controles secundarios.
Con la llegada de ASP.NET 4, tenemos una nueva propiedad llamada ViewStateMode que se puede usar para habilitar el estado de vista para un control individual, incluso si el estado de vista está deshabilitado para la página.
Para hacer uso de esta nueva propiedad, puede crear una clase de página base que establezca ViewStateMode en Disabled o cree un PageAdapter que haga lo mismo. No hay propiedad viewStateMode en web.config.
Aquí está el código para el adaptador de página:
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);
}
}
}
y aquí está el código para el archivo del navegador:
<browser refID="default">
<controladapters>
<adapter controlType="System.Web.UI.Page" adapterType="Playground.Web.UI.Adapters.PageAdapter" />
</controladapters>
</browser>
Cuando deshabilito ViewState para la página. No permite que ningún otro control use ViewState ... incluso si configuro EnableViewState = "true" para ese control en particular.
¿Es posible habilitar ViewState para un control cuando ViewState está deshabilitado para la página en sí?
de lo contrario, ¿cómo puede deshabilitar viewstate para los controles en la página, excepto para unos pocos sin especificar EnableViewState = "false" explícitamente ... escribiendo el mismo en tantos controles es agitado ..
Aquí hay un código que se expande sobre el concepto de @Samuel Kim de tener una forma de deshabilitar ViewState en todos los controles salvo ciertos (por cierto, usa .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;
}
Lo único que no estoy 100% seguro (y no tengo mi máquina virtual en ejecución) es si Page.Controles necesita ser lanzado o no, de ser así solo tenga esto en su lugar:
IEnumerable<Control> controlsWithoutViewState = Page.Controls.Cast<Control>().Where(c => !allowedControls.Contains(c.ID));
Lo anterior es solo un concepto rápido de qué hacer, no tiene en cuenta los controles anidados en los que puede querer 1 con y 1 sin ViewState, pero no sería difícil hacer una función recusiva para manejarlo.
Con .NET 4.0 también puede definir los adaptadores de control
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);
}
}
}
En el código anterior, el modo ViewState está deshabilitado cuando se hereda. Agregue la siguiente línea en el archivo de configuración del navegador.
<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>
De esta forma, puede tener un cotnrol más granular sobre viewstate para cada control individual a lo largo de la aplicación. Y donde necesita control para tener viewstate simplemente habilítelo en el código. Eso es.
La solución más simple es:
<%@ Page Language="C#" EnableViewState="true" ViewStateMode="Disabled" %>
y donde quiera habilitar Viewstate:
<asp:yourcontrol EnableViewState="true" ViewStateMode="Enabled">
Todos los créditos reservados a la respuesta de Shredder en esta publicación
Si desactiva ViewState de la página de turno, entonces no hay forma de que habilite ViewState para componentes específicos. Esto se debe a que ViewState se serializa de forma recursiva, por lo tanto, si la página no permite ViewState, no serializará ViewState para ninguno de sus controles secundarios.
En respuesta a su pregunta, si no desea desactivar ViewState explícitamente en los controles individuales, pero quiere mantener algunos controles con ViewState consciente, la mejor manera sería escribir un pequeño método de utilidad que desactive ViewState para todos los controles (utilizando recursion o de otro modo). Luego habilite ViewState para los controles que le gustaría habilitar ViewState.
Alternativamente, un camino intermedio y menos contundente puede ser posible si los controles son grupos dentro de otros controles de contenedor (como el Panel). Puede deshabilitar ViewState para todos los controles dentro de un Panel deshabilitando ViewState del Panel.
También puede crear una subclase de los controles integrados, y en su subclase establecer la propiedad EnableViewState en falso.
También puede heredar de una página base. En la BasePage, deshabilite 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;
}
}
En cada página que desee que ViewState Enabled, haga lo siguiente en Page_Load:
public partial class Products_Default : BasePage {
protected void Page_Load(object sender, EventArgs e) {
this.ViewStateEnabled = true;
}
}
Esto debería habilitar ViewState solo para esa página (asumiendo que está activado en la página maestra). Nota: Necesitará establecer individualmente el ViewState de cada control en esa página.
Tengo curiosidad por ver si el enfoque de Samuel funciona. Si lo intenta, publique su resultado.
No digo que Samuel esté equivocado, solo sería curioso.
La razón por la que tengo curiosidad es porque Viewstate se serializa recursivamente (como mencionó Samuel) si tenía un control con viewstate habilitado que era un elemento secundario de un control con viewstate deshabilitado, entonces el control secundario no tendría viewstate porque la serialización recursiva saltaría por completo en el nivel principal. Esto sería específicamente problemático si ha construido sus propios controles de usuario que naturalmente contendrían muchos controles secundarios.
Otra solución sería utilizar el método de utilidad de Samuel, pero en lugar de deshabilitar todo, simplemente deshabilítelo para controles como Label, Literal, etc. que no tienen hijos ... o si tienen hijos, está bien si los niños tienen viewstate deshabilitado.
Naturalmente, querrá evitar deshabilitar el estado visual de Paneles y Marcadores de posición por el motivo que indiqué anteriormente.
Editar:
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