Risolvere i problemi di viewstate non validi

Questo articolo presenta le tecniche per il debug e la risoluzione dei problemi relativi allo stato di visualizzazione nelle applicazioni microsoft ASP.NET.

Versione originale del prodotto: ASP.NET
Numero KB originale: 829743

Introduzione

Viewstate è una funzionalità in ASP.NET che consente alle pagine di mantenere automaticamente lo stato senza basarsi sullo stato del server, ad esempio lo stato della sessione. Tuttavia, i problemi relativi allo stato di visualizzazione possono essere difficili da eseguire. Nella maggior parte dei casi, quando si verificano problemi con viewstate, viene visualizzato il messaggio di errore seguente nel Web browser, con poche indicazioni su cosa potrebbe causare il problema:

Lo stato di visualizzazione non è valido per questa pagina e potrebbe essere danneggiato.

Questo articolo descrive alcune tecniche che possono essere usate per il debug e per risolvere i problemi con viewstate.

Impostare l'attributo validationKey se si esegue in una web farm

In una web farm, ogni richiesta client può passare a un computer diverso in ogni postback. A causa di questo comportamento, non è possibile lasciare l'attributo validationKey impostato su AutoGenerate nel file Machine.config . È invece necessario impostare il valore dell'attributo validationKey su una stringa fissa condivisa da tutti i computer nella Web farm.

Non archiviare tipi generati dinamicamente in viewstate in una web farm

Quando ASP.NET compila i file in modo dinamico, i file vengono incorporati in assembly con nomi casuali ( ad esempio, un nome di file potrebbe essere jp395dun.dll). Se si esegue una web farm, gli stessi file vengono compilati in assembly con nomi casuali diversi. In genere, questo non è un problema perché nessuno fa ipotesi su tali nomi di assembly. Tuttavia, se si inserisce un tipo compilato dinamicamente in viewstate usando la serializzazione binaria, il nome dell'assembly viene incluso come parte dei dati dello stato di visualizzazione. Quando lo stato di visualizzazione viene inviato in un secondo momento a un server diverso nella web farm, lo stato di visualizzazione non può essere deserializzato perché usa nomi di assembly diversi.

La soluzione migliore consiste nell'evitare di usare la serializzazione binaria. La serializzazione binaria usa molte risorse anche quando non si verifica questo problema. Limitare invece gli elementi inseriti in viewstate a una combinazione di matrici, coppie, triplette e tipi semplici, ad esempio stringhe, int e altri tipi. System.Web.UI.Pair e System.Web.UI.Triplet sono tipi wrapper semplici che il motore viewstate può elaborare in modo efficiente.

Una soluzione alternativa per evitare questo problema consiste nello spostare i tipi archiviati in viewstate in un assembly precompilato, nella Bin cartella o nella Global Assembly cache. Questa correzione non risolve le prestazioni, ma garantisce che l'assembly abbia lo stesso nome in tutti i computer.

Nota

Se si archiviano tipi di dati complessi in viewstate e si verifica questo problema, le informazioni sullo stack di chiamate conterrà stack simili ai seguenti:

[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

Lo scopo della funzionalità MAC (ViewState Machine Authentication Code) è rendere impossibile per i client inviare una richiesta contenente uno stato di visualizzazione dannoso. Per impostazione predefinita, questa funzionalità è abilitata nel flag seguente nel file Machine.config .

enableViewStateMac="true"

Il modo più semplice per determinare se il problema che si sta affrontando è correlato alla funzionalità MAC consiste nel disattivare la funzionalità. A tale scopo, modificare il flag nel file Machine.config nel codice seguente.

enableViewStateMac="false"

Se non si ottengono più errori di viewstate, il problema è correlato alla funzionalità MAC.

Importante

Disattivare solo la funzionalità MAC viewstate per diagnosticare il problema. Non è consigliabile mantenere il viewstate MAC disattivato per risolvere il problema. Se lo fai, potresti introdurre buchi di sicurezza. Per altre informazioni, vedere Compilazione di applicazioni ASP.NET sicure: autenticazione, autorizzazione e comunicazione sicura.

Se si disattiva la funzionalità MAC viewstate e quindi si usa viewstate per i controlli che non codificano html (ad esempio, un controllo Label), gli utenti malintenzionati possono manomettere i dati dello stato di visualizzazione e inserire dati arbitrari nello stato di visualizzazione. Questi dati arbitrari vengono decodificati e quindi usati dai controlli quando eseguono il rendering della pagina pubblicata. Di conseguenza, gli utenti malintenzionati possono inserire script nell'applicazione a meno che non si lavori per impedire l'attacco. Ad esempio, un utente malintenzionato potrebbe decodificare i dati, inserire script nei dati in cui si trova un controllo Label e quindi collegarli da un sito Web. Chiunque fa clic sul collegamento è vittima di un attacco di script injection che potrebbe potenzialmente rubare i cookie di autenticazione o l'ID sessione. Lo script potrebbe anche consentire a un utente malintenzionato di modificare i dati sullo stato per i controlli che usano viewstate e attacchi specifici dell'applicazione potrebbero verificarsi di conseguenza.

In generale, Microsoft consiglia di non disattivare la funzionalità MAC dello stato di visualizzazione, a meno che non si sia certi di aver disabilitato lo stato di visualizzazione per tutti i controlli che non codificano l'output (ad esempio, i controlli DataGrid, i controlli DataList, i controlli Label e altri controlli) come HTML o di impostare sempre in modo esplicito i valori di ogni richiesta su un elemento noto come sicuro.

Determinare esattamente quale eccezione si verifica quando si riceve il messaggio di errore

Purtroppo, il messaggio di errore viewstate non valido menzionato nella sezione Introduzione di questo articolo non è informativo. Il messaggio di errore è causato da un'eccezione generata durante l'elaborazione dello stato di visualizzazione. Il problema è che l'eccezione viene usata e i relativi dettagli vengono persi nel messaggio di errore.

Usando un debugger, è possibile determinare l'eccezione originale. A tale scopo, è necessario collegare un debugger al processo di ASP.NET (Aspnet_wp.exe o W3wp.exe) e quindi impostarlo per intercettare tutte le eccezioni. Il debugger probabilmente si arresterà con alcune eccezioni che non sono rilevanti, ma alla fine raggiungerà l'eccezione viewstate e fornirà informazioni utili per la risoluzione dei problemi.

I passaggi seguenti sono un esempio che usa il debugger di runtime (Cordbg.exe).

  1. Al prompt dei comandi eseguire il iisreset comando per assicurarsi di avere un buon punto di partenza e quindi passare a una pagina del sito.

  2. Eseguire cordbg.exe.

  3. Digitare <pro>e quindi premere INVIO. Verrà visualizzato un elenco di processi gestiti. Verrà visualizzato il Aspnet_wp.exe o il processo diW3wp.exe . Prendere nota del relativo PID.

  4. Digitare un <PID>oggetto .

    Nota

    Sostituire PID con il PID annotato nel passaggio 3.

  5. Digitare ca e per indicare a Cordbg.exe di interrompere tutte le eccezioni e quindi digitare <gto> esegui il processo.

  6. Ogni volta che si ottiene un'eccezione, digitare <w> per visualizzare lo stack. Se lo stack è un'eccezione viewstate (cercare LoadPageStateFromPersistenceMedium nello stack), copiare tutte le eccezioni e le informazioni sullo stack dalla finestra di comando e quindi salvare le informazioni. Queste informazioni consentono di comprendere il problema. Se l'eccezione non è correlata, digitare <g>.

Provare a archiviare lo stato di visualizzazione nella sessione

Per impostazione predefinita, lo stato di visualizzazione viene arrotondato con un <input type=hidden> campo inviato al browser. Il browser invia quindi il campo al server alla richiesta successiva. In alcuni casi, questo viewstate può diventare grande ed essere una potenziale fonte di problemi. Alcuni browser non possono gestire un campo nascosto così grande (e la richiesta di grandi dimensioni risultante) e i browser potrebbero troncare lo stato di visualizzazione. Il troncamento dello stato di visualizzazione genera un messaggio di errore "viewstate danneggiato". Questo comportamento è più probabile che si verifichi in browser più semplici. Ad esempio, questo comportamento può verificarsi in un browser in un PDA.

Per determinare se si potrebbe riscontrare un problema di questo tipo, provare a archiviare lo stato di visualizzazione nella sessione. Nell'esempio seguente viene illustrato come eseguire questa operazione.

<%@ 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> 

Determinare se il problema è causato dal riciclo del processo di lavoro

Considerate il seguente scenario:

  • Si esegue ASP.NET in Microsoft Internet Information Services (IIS) 6.0.
  • Il pool di applicazioni è in esecuzione con un'identità diversa dall'account del sistema locale, dall'account del servizio di rete o da un account a livello amministrativo.
  • L'attributo validationKey dell'elemento <machineKey> è impostato su nel file di AutoGenerate configurazione.

In questo scenario, la procedura seguente causa l'errore viewstate:

  1. Un utente esplora una pagina.
  2. Processo di lavoro che ospita il riciclo dell'applicazione ASP.NET.
  3. L'utente esegue il postback della pagina.

Come soluzione alternativa per questo scenario, usare un attributo esplicito validationKey nel file di configurazione.

Riferimenti