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
Determinare se il problema è correlato alla funzionalità MAC viewstate
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).
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.Eseguire
cordbg.exe
.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.Digitare un
<PID>
oggetto .Nota
Sostituire PID con il PID annotato nel passaggio 3.
Digitare ca e per indicare a Cordbg.exe di interrompere tutte le eccezioni e quindi digitare
<gto>
esegui il processo.Ogni volta che si ottiene un'eccezione, digitare
<w>
per visualizzare lo stack. Se lo stack è un'eccezione viewstate (cercareLoadPageStateFromPersistenceMedium
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 diAutoGenerate
configurazione.
In questo scenario, la procedura seguente causa l'errore viewstate:
- Un utente esplora una pagina.
- Processo di lavoro che ospita il riciclo dell'applicazione ASP.NET.
- L'utente esegue il postback della pagina.
Come soluzione alternativa per questo scenario, usare un attributo esplicito validationKey
nel file di configurazione.
Riferimenti
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per