Compartir a través de


Solución de problemas relacionados con viewstate no válido

En este artículo se presentan técnicas para depurar y resolver problemas con viewstate en aplicaciones de Microsoft ASP.NET.

Versión original del producto: ASP.NET
Número de KB original: 829743

Introducción

Viewstate es una característica de ASP.NET que permite a las páginas conservar automáticamente el estado sin depender del estado del servidor (por ejemplo, estado de sesión). Sin embargo, los problemas relacionados con viewstate pueden ser difíciles de depurar. En la mayoría de los casos, cuando se producen problemas con viewstate, recibirá el siguiente mensaje de error en el explorador web, con poca indicación de lo que podría estar causando el problema:

El valor viewstate no es válido para esta página y podría estar dañado.

En este artículo se describen algunas técnicas que se pueden usar para la depuración y para resolver problemas con viewstate.

Establezca el atributo validationKey si se ejecuta en una granja de servidores web.

En una granja de servidores web, cada solicitud de cliente puede ir a una máquina diferente en cada postback. Debido a este comportamiento, no se puede dejar el validationKey atributo establecer AutoGenerate en el archivo Machine.config. En su lugar, debe establecer el valor del validationKey atributo en una cadena fija compartida por todas las máquinas de la granja de servidores web.

No almacene tipos generados dinámicamente en viewstate en una granja de servidores web

Cuando ASP.NET compila archivos dinámicamente, los archivos se integran en ensamblados con nombres aleatorios (por ejemplo, un nombre de archivo podría ser jp395dun.dll). Si ejecuta una granja de servidores web, los mismos archivos se compilan en ensamblados con nombres aleatorios diferentes. Normalmente, no es un problema porque nadie hace suposiciones sobre esos nombres de ensamblaje. Pero si alguna vez coloca un tipo compilado dinámicamente en viewstate mediante la serialización binaria, el nombre del ensamblado se incluye como parte de los datos viewstate. Cuando ese viewstate se envía más adelante a un servidor diferente de la granja de servidores web, no se puede deserializar el viewstate porque utiliza nombres de ensamblado diferentes.

La mejor resolución es evitar el uso de la serialización binaria. La serialización binaria usa muchos recursos incluso cuando no se encuentra con este problema. En su lugar, limite lo que se coloca en viewstate a una combinación de matrices, pares, triples y tipos simples (por ejemplo, cadenas, int y otros tipos). System.Web.UI.Pair y System.Web.UI.Triplet son tipos de contenedor simples que el motor viewstate puede procesar de forma eficaz.

Una corrección alternativa para evitar este problema es mover los tipos que se están almacenando en el viewstate a un ensamblado precompilado, ya sea en la carpeta Bin o en la memoria caché Global Assembly. Esta corrección no aborda el rendimiento, pero garantiza que el ensamblado tiene el mismo nombre en todos los equipos.

Nota:

Si almacena tipos de datos complejos en viewstate y experimenta este problema, la información de la pila de llamadas contiene las siguientes pilas:

[FileNotFoundException: Could not load file or assembly 'App_Web_fx--sar9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.]
 System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName) +0
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +72
System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +58
System.Type.GetType(String typeName, Boolean throwOnError) +57
System.Web.UI.ObjectStateFormatter.DeserializeType(SerializerBinaryReader reader) +192 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +943 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +384 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +210 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +142

El propósito de la característica del código de autenticación del estado de vista de la máquina (MAC) es hacer imposible que los clientes envíen una solicitud que contenga un viewstate malicioso. De forma predeterminada, esta característica está habilitada en la marca siguiente en el archivo Machine.config .

enableViewStateMac="true"

La manera más sencilla de determinar si el problema con el que se está tratando está relacionado con la característica MAC es desactivar la característica. Para desactivar la característica, cambie la marca en el archivo Machine.config por el código siguiente.

enableViewStateMac="false"

Si ya no obtienes errores de viewstate, el problema está relacionado con la función MAC.

Importante

Desactive solo la característica MAC de viewstate para ayudar a diagnosticar el problema. No debe mantener desactivado el ViewState MAC como solución al problema. Si lo hace, podría introducir agujeros de seguridad. Para obtener más información, consulte Building Secure ASP.NET Applications: Autenticación, Autorización y Comunicación Segura.

Si desactiva la característica MAC de viewstate y, a continuación, usa viewstate para los controles que no codifican HTML (por ejemplo, un control Label), los atacantes pueden alterar los datos viewstate y pueden colocar datos arbitrarios en viewstate. Estos datos arbitrarios se descodifican y, a continuación, los usan los controles cuando representan la página publicada. Como resultado, los atacantes pueden insertar scripts en la aplicación a menos que trabaje para evitar el ataque. Por ejemplo, un atacante podría descodificar los datos, insertar script en los datos donde está un control Label y, a continuación, vincularlos desde un sitio web. Cualquier persona que seleccione el vínculo sería víctima de un ataque de inyección de script que podría robar sus cookies de autenticación o identificador de sesión. El script también podría permitir que un atacante modifique los datos de estado de los controles que usan viewstate y ataques específicos de la aplicación podrían producirse como resultado.

En general, Microsoft recomienda que no desactive la característica MAC de viewstate, a menos que esté seguro de que ha deshabilitado viewstate para todos los controles que no codifican su salida (por ejemplo, controles DataGrid, controles DataList, controles Label y otros controles) como HTML o que siempre establece explícitamente sus valores en cada solicitud a algo que se sabe que es seguro.

Determine exactamente qué excepción se produce cuando recibe el mensaje de error

Desafortunadamente, el mensaje de error viewstate no válido que se encuentra en la sección Introducción de este artículo no es informativo. El mensaje de error se debe a que se genera una excepción cuando se procesa el estado de vista. El problema es que se consume la excepción y sus detalles se pierden en el mensaje de error.

Mediante un depurador, puede determinar la excepción original. Para ello, debe adjuntar un depurador al proceso de ASP.NET (Aspnet_wp.exe o W3wp.exe) y, a continuación, establecerlo para detectar todas las excepciones. El depurador probablemente se detiene en algunas excepciones que no son relevantes, pero finalmente alcanza la excepción viewstate y proporciona información útil para solucionar problemas.

Los pasos siguientes son un ejemplo que usa el depurador en tiempo de ejecución (Cordbg.exe).

  1. En el símbolo del sistema, ejecute el comando iisreset para asegurarse de tener un buen punto de partida y, a continuación, vaya a una página en su sitio.

  2. Ejecute cordbg.exe.

  3. Escriba <pro>y presione ENTRAR. Aparecerá una lista de procesos administrados. Debería ver el proceso Aspnet_wp.exe o el W3wp.exe. Anote su PID.

  4. Escriba un <PID>.

    Nota:

    Reemplace PID por el PID que se anotó en el paso 3.

  5. Escriba ca e para indicar a Cordbg.exe que interrumpa sobre/durante todas las excepciones, y luego escriba <gto> para ejecutar el proceso.

  6. Siempre que obtenga una excepción, escriba <w> para ver la pila. Si la pila es una excepción viewstate (busque LoadPageStateFromPersistenceMedium en la pila), copie todas las excepciones y la información de la pila desde la ventana de comandos y guarde la información. Esta información puede ayudarle a comprender el problema. Si la excepción no está relacionada, escriba <g>.

Intente almacenar el viewstate en la sesión.

De forma predeterminada, el valor viewstate se realiza de ida y vuelta con un <input type=hidden> campo que se envía al explorador. A continuación, el explorador devuelve el campo al servidor en la siguiente solicitud. En algunos casos, este estado de vista puede ser grande y ser un posible origen de problemas. Algunos navegadores no pueden gestionar un campo oculto de gran tamaño (y la solicitud grande resultante), y los navegadores podrían truncar el estado de visualización. Truncar el viewstate provoca un mensaje de error "viewstate corrupted". Este comportamiento es más probable que se produzca en exploradores más sencillos. Por ejemplo, este comportamiento puede producirse en un explorador en un PDA.

Para determinar si podría estar enfrentándose a este problema, intente almacenar el estado de visualización en la sesión. En el ejemplo siguiente se muestra cómo hacerlo:

<%@ language=c# debug=true %> 

<script runat=server> 
protected override object LoadPageStateFromPersistenceMedium() 
{ 
    return Session["_ViewState"]; 
}

protected override void SavePageStateToPersistenceMedium(object viewState) 
{ 
    Session["_ViewState"] = viewState; 
}

void TextChanged(object o, EventArgs e) 
{ 
    Response.Write("TextChanged"); 
} 
</script> 
<form runat=server> 
<asp:button text=Test runat=server/> 
<asp:textbox ontextchanged=TextChanged runat=server/> 
<input type=hidden name=__VIEWSTATE> 
</form> 

Determinar si el reciclaje de procesos de trabajo provoca el problema

Considere el siguiente escenario:

  • Está ejecutando ASP.NET en Microsoft Internet Information Services (IIS) 6.0.
  • El grupo de aplicaciones se ejecuta en una identidad distinta de la cuenta del sistema local, la cuenta de servicio de red o una cuenta de nivel administrativo.
  • El validationKey atributo del <machineKey> elemento se establece AutoGenerate en en el archivo de configuración.

En este escenario, el procedimiento siguiente hace que se produzca un error viewstate:

  1. Un usuario examina una página.
  2. El proceso de trabajo que hospeda la aplicación ASP.NET se recicla.
  3. El usuario publica de nuevo la página.

Como solución alternativa para este escenario, use un atributo explícito validationKey en el archivo de configuración.

Referencias