Behandeln von Problemen mit ungültigen Ansichtszuständen

In diesem Artikel werden Techniken zum Debuggen und Beheben von Problemen mit Viewstate in Microsoft ASP.NET-Anwendungen vorgestellt.

              Originale Produktversion: ASP.NET
Ursprüngliche KB-Nummer: 829743

Einführung

Viewstate ist ein Feature in ASP.NET, das es Seiten ermöglicht, den Zustand automatisch beizubehalten, ohne sich auf den Serverzustand zu verlassen (z. B. sitzungszustand). Probleme im Zusammenhang mit Viewstate können jedoch schwierig zu debuggen sein. In den meisten Fällen erhalten Sie, wenn Probleme mit viewstate auftreten, die folgende Fehlermeldung im Webbrowser mit wenig Hinweis darauf, was das Problem verursachen könnte:

Der Ansichtszustand ist für diese Seite ungültig und möglicherweise beschädigt.

In diesem Artikel werden einige Techniken beschrieben, die zum Debuggen und beheben von Problemen mit viewstate verwendet werden können.

Festlegen des validationKey-Attributs, wenn Sie in einer Webfarm ausgeführt werden

In einer Webfarm kann jede Clientanforderung bei jedem Postback an einen anderen Computer gehen. Aufgrund dieses Verhaltens können Sie das Attribut in der validationKeyMachine.config Datei nicht auf AutoGenerate festlegen. Stattdessen müssen Sie den Wert des validationKey Attributs auf eine feste Zeichenfolge festlegen, die von allen Computern in der Webfarm gemeinsam verwendet wird.

Speichern dynamisch generierter Typen nicht in viewstate in einer Webfarm

Wenn ASP.NET Dateien dynamisch kompiliert, werden die Dateien in Assemblys mit zufälligen Namen integriert (ein Dateiname kann z. B.jp395dun.dllsein). Wenn Sie eine Webfarm ausführen, werden dieselben Dateien in Assemblys mit unterschiedlichen zufälligen Namen kompiliert. Normalerweise ist dies kein Problem, da niemand Annahmen zu diesen Assemblynamen annimmt. Wenn Sie jedoch jemals einen dynamisch kompilierten Typ mithilfe der binären Serialisierung in viewstate einfügen, wird der Name der Assembly als Teil der Viewstate-Daten eingeschlossen. Wenn dieser Ansichtszustand später an einen anderen Server in der Webfarm gesendet wird, kann der Ansichtszustand nicht deserialisiert werden, da er unterschiedliche Assemblynamen verwendet.

Die beste Lösung besteht darin, die Verwendung der binären Serialisierung zu vermeiden. Bei der binären Serialisierung werden viele Ressourcen verwendet, auch wenn dieses Problem nicht auftritt. Beschränken Sie stattdessen das, was Sie in viewstate einfügen, auf eine Kombination aus Arrays, Paaren, Triplets und einfachen Typen (z. B. Zeichenfolgen, int und andere Typen). System.Web.UI.Pair und System.Web.UI.Triplet sind einfache Wrappertypen, die die ViewState-Engine effizient verarbeiten kann.

Eine alternative Lösung, um dieses Problem zu vermeiden, besteht darin, die typen, die Sie in viewstate speichern, in eine vorkompilierte Assembly zu verschieben, entweder in Ihrem Bin Ordner oder im Global Assembly Cache. Dieser Fix adressiert nicht die Leistung, garantiert aber, dass die Assembly auf allen Computern denselben Namen hat.

Hinweis

Wenn Sie komplexe Datentypen in viewstate speichern und dieses Problem auftreten, enthalten die Aufruflisteninformationen Stapel, die den folgenden ähneln:

[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

Der Zweck des Mac-Features (Machine Authentication Code) von Viewstate besteht darin, clients das Senden einer Anforderung, die einen schädlichen Viewstate enthält, unmöglich zu machen. Dieses Feature ist standardmäßig im folgenden Flag in der Machine.config-Datei aktiviert.

enableViewStateMac="true"

Die einfachste Möglichkeit, zu ermitteln, ob das Problem, mit dem Sie es zu tun haben, mit dem MAC-Feature zusammenhängt, besteht darin, das Feature zu deaktivieren. Ändern Sie dazu das Flag in der Machine.config-Datei in den folgenden Code.

enableViewStateMac="false"

Wenn sie keine Viewstate-Fehler mehr erhalten, hängt das Problem mit dem MAC-Feature zusammen.

Wichtig

Deaktivieren Sie nur das MAC-Feature viewstate, um das Problem zu diagnostizieren. Sie sollten den Viewstate-MAC nicht deaktiviert lassen, um das Problem zu umgehen. Wenn Sie dies tun, könnten Sie Sicherheitslücken einführen. Weitere Informationen finden Sie unter Erstellen sicherer ASP.NET Anwendungen: Authentifizierung, Autorisierung und sichere Kommunikation.

Wenn Sie das MAC-Feature viewstate deaktivieren und dann viewstate für Steuerelemente verwenden, die nicht HTML-codieren (z. B. ein Label-Steuerelement), können Angreifer die Viewstate-Daten manipulieren und beliebige Daten in viewstate ablegen. Diese beliebigen Daten werden decodiert und dann von Steuerelementen verwendet, wenn sie die gepostete Seite rendern. Daher können Angreifer Skripts in die Anwendung einfügen, es sei denn, Sie arbeiten daran, den Angriff zu verhindern. Beispielsweise könnte ein Angreifer die Daten decodieren, skripts in die Daten einfügen, in denen sich ein Label-Steuerelement befindet, und dann von einer Website aus eine Verknüpfung damit herstellen. Jeder, der auf den Link klickt, wird Opfer eines Skripteinschleusungsangriffs, der möglicherweise seine Authentifizierungscookies oder sitzungs-ID stehlen könnte. Das Skript könnte es einem Angreifer auch ermöglichen, Zustandsdaten für Steuerelemente zu ändern, die viewstate verwenden, und anwendungsspezifische Angriffe können als Ergebnis auftreten.

Im Allgemeinen empfiehlt Microsoft, das MAC-Feature viewstate nicht zu deaktivieren, es sei denn, Sie sind sicher, dass Sie entweder viewstate für alle Steuerelemente deaktiviert haben, die ihre Ausgabe nicht codieren (z. B. DataGrid-Steuerelemente, DataList-Steuerelemente, Bezeichnungssteuerelemente und andere Steuerelemente) als HTML oder dass Sie ihre Werte bei jeder Anforderung immer explizit auf etwas festlegen, das als sicher gilt.

Bestimmen Sie genau, welche Ausnahme auftritt, wenn Sie die Fehlermeldung erhalten.

Leider ist die im Abschnitt Einführung dieses Artikels erwähnte ungültige Viewstate-Fehlermeldung nicht informativ. Die Fehlermeldung wird durch eine Ausnahme verursacht, die generiert wird, wenn der ViewState verarbeitet wird. Das Problem besteht darin, dass die Ausnahme genutzt wird und ihre Details in der Fehlermeldung verloren gehen.

Mithilfe eines Debuggers können Sie die ursprüngliche Ausnahme bestimmen. Dazu müssen Sie einen Debugger an den ASP.NET Prozess anfügen (Aspnet_wp.exe oder W3wp.exe), und dann festlegen, dass alle Ausnahmen abfangen werden. Der Debugger wird wahrscheinlich bei einigen Ausnahmen angehalten, die nicht relevant sind, aber schließlich trifft er auf die Viewstate-Ausnahme und stellt nützliche Informationen zur Problembehandlung bereit.

Die folgenden Schritte sind ein Beispiel für die Verwendung des Laufzeitdebuggers (Cordbg.exe).

  1. Führen Sie an der Eingabeaufforderung den iisreset Befehl aus, um sicherzustellen, dass Ihnen ein guter Ausgangspunkt zur Verfügung steht, und navigieren Sie dann zu einer Seite auf Ihrer Website.

  2. Führen Sie cordbg.exe aus.

  3. Geben Sie ein <pro>, und drücken Sie dann die EINGABETASTE. Eine Liste der verwalteten Prozesse wird angezeigt. Es sollte entweder der Aspnet_wp.exe oder der W3wp.exe-Prozess angezeigt werden. Notieren Sie sich die PID.

  4. Geben Sie ein ein <PID>.

    Hinweis

    Ersetzen Sie PID durch die PID, die in Schritt 3 notiert wurde.

  5. Geben Sie ca e ein, um Cordbg.exe anzuweisen, bei allen Ausnahmen zu unterbrechen, und geben Sie <gto> dann den Prozess ausführen ein.

  6. Wenn Sie eine Ausnahme erhalten, geben Sie ein <w> , um den Stapel anzuzeigen. Wenn es sich bei dem Stapel um eine Ansichtszustandsausnahme handelt (suchen Sie LoadPageStateFromPersistenceMedium im Stapel nach), kopieren Sie alle Ausnahmen und stapelinformationen aus dem Befehlsfenster, und speichern Sie dann die Informationen. Diese Informationen können Ihnen helfen, das Problem zu verstehen. Wenn die Ausnahme nicht verknüpft ist, geben Sie ein <g>.

Versuchen Sie, den Viewstate in der Sitzung zu speichern.

Standardmäßig wird der Ansichtszustand mit einem <input type=hidden> Feld roundtrippediert, das an den Browser gesendet wird. Der Browser sendet das Feld dann bei der nächsten Anforderung zurück an den Server. In einigen Fällen kann dieser Ansichtszustand groß werden und eine potenzielle Problemquelle sein. Einige Browser können ein so großes ausgeblendetes Feld (und die resultierende große Anforderung) nicht verarbeiten, und die Browser können den Ansichtszustand abschneiden. Das Abschneiden des Viewstates führt zur Fehlermeldung "viewstate corrupted". Dieses Verhalten tritt höchstwahrscheinlich in einfacheren Browsern auf. Dieses Verhalten kann beispielsweise in einem Browser auf einem PDA auftreten.

Um festzustellen, ob ein solches Problem auftreten kann, versuchen Sie, den Viewstate in der Sitzung zu speichern. Im folgenden Beispiel wird dies veranschaulicht.

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

Ermitteln, ob das Problem durch das Recycling des Arbeitsprozesses verursacht wird

Stellen Sie sich folgendes Szenario vor:

  • Sie führen ASP.NET unter Microsoft-Internetinformationsdienste (IIS) 6.0 aus.
  • Der Anwendungspool wird unter einer anderen Identität als dem lokalen Systemkonto, dem Netzwerkdienstkonto oder einem Administratorkonto ausgeführt.
  • Das validationKey -Attribut des <machineKey> -Elements wird in der Konfigurationsdatei auf AutoGenerate festgelegt.

In diesem Szenario verursacht die folgende Prozedur einen Ansichtszustandsfehler:

  1. Ein Benutzer durchsucht eine Seite.
  2. Der Arbeitsprozess, der die ASP.NET Anwendung hostet, wird wiederverwendet.
  3. Der Benutzer stellt die Seite zurück.

Verwenden Sie als Problemumgehung für dieses Szenario ein explizites validationKey Attribut in der Konfigurationsdatei.

References