Freigeben über


Fehlerbehebung bei ungültigen Viewstate-Problemen

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

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

Einführung

"Viewstate" ist ein Feature in ASP.NET, mit dem Seiten den Zustand automatisch beibehalten können, 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 Ansichtsstatus ist für diese Seite ungültig und ist möglicherweise beschädigt.

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

Legen Sie das ValidationKey-Attribut fest, wenn Sie in einer Web-Farm arbeiten.

In einer Webfarm kann jede Clientanforderung auf jedem Postback zu einem anderen Computer wechseln. Aufgrund dieses Verhaltens können Sie das validationKey Attribut im Machine.config nicht auf AutoGenerate lassen. Stattdessen müssen Sie den Wert des validationKey Attributs auf eine feste Zeichenfolge festlegen, die von allen Computern in der Webfarm gemeinsam verwendet wird.

Dynamisch generierte Typen nicht im ViewState in einer Webfarm speichern

Wenn ASP.NET Dateien dynamisch kompiliert, werden die Dateien in Assemblys mit zufälligen Namen integriert (z. B. kann ein Dateiname jp395dun.dll werden). Wenn Sie eine Webfarm ausführen, werden dieselben Dateien in Assemblys mit unterschiedlichen zufälligen Namen kompiliert. Normalerweise ist es kein Problem, da niemand Annahmen über diese Assembly-Namen trifft. Wenn Sie jedoch jemals einen dynamisch kompilierten Typ durch binäre Serialisierung in den Viewstate einfügen, wird der Name der Assembly als Teil der Viewstate-Daten enthalten. Wenn dieser Ansichtsstatus später an einen anderen Server in der Webfarm gesendet wird, kann der Ansichtsstatus nicht deserialisiert werden, da er unterschiedliche Assemblynamen verwendet.

Die beste Auflö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, was Sie in viewstate auf eine Kombination aus Arrays, Paaren, Triplets und einfachen Typen setzen (z. B. Zeichenfolgen, Int und andere Typen). System.Web.UI.Pair und System.Web.UI.Triplet sind einfache Wrappertypen, die das Viewstate-Modul 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 behebt keine Leistung, garantiert jedoch, dass die Assembly auf allen Computern denselben Namen hat.

Notiz

Wenn Sie komplexe Datentypen im View-State speichern und dieses Problem auftritt, enthalten die Aufrufstapel-Informationen die folgenden Stapel:

[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 ViewState Machine Authentication Code (MAC) Features besteht darin, es Clients unmöglich zu machen, eine Anforderung zu senden, die einen manipulierten ViewState enthält. Dieses Feature ist standardmäßig in der Datei "Machine.config" im folgenden Flag aktiviert.

enableViewStateMac="true"

Die einfachste Möglichkeit, zu bestimmen, ob das Problem, mit dem Sie arbeiten, mit dem MAC-Feature in Zusammenhang steht, besteht darin, das Feature zu deaktivieren. Um das Feature zu deaktivieren, ändern Sie das Kennzeichen in der Machine.config-Datei in den folgenden Code.

enableViewStateMac="false"

Wenn keine Viewstate-Fehler mehr auftreten, bezieht sich das Problem auf die MAC-Funktion.

Wichtig

Deaktivieren Sie nur das Viewstate MAC-Feature, um das Problem zu diagnostizieren. Sie sollten den ViewState-MAC nicht ausgeschaltet lassen, um das Problem zu umgehen. Wenn Sie dies tun, könnten Sie Sicherheitslöcher einführen. Weitere Informationen finden Sie unter Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication.

Wenn Sie das Viewstate-MAC-Feature deaktivieren und dann Viewstate für Steuerelemente verwenden, die keine HTML-Codierung aufweisen (z. B. ein Bezeichnungssteuerelement), können Angreifer die Viewstate-Daten manipulieren und beliebige Daten in den Viewstate einfügen. 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, Skript in die Daten einfügen, in denen sich ein Bezeichnungssteuerelement befindet, und dann von einer Website aus darauf verknüpfen. Jeder, der den Link auswählt, wäre das Opfer eines Skriptinjektionsangriffs, der möglicherweise ihre Authentifizierungscookies oder Sitzungs-ID stehlen könnte. Das Skript könnte auch zulassen, dass ein Angreifer Zustandsdaten für Steuerelemente ändert, die Viewstate und anwendungsspezifische Angriffe verwenden, als Ergebnis auftreten können.

Im Allgemeinen empfiehlt Microsoft, die Ansichtsstatus-MAC-Funktion nicht zu deaktivieren, es sei denn, Sie sind sicher, dass Sie entweder den Ansichtsstatus 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 immer explizit für jede Anforderung festlegen, die als sicher bekannt ist.

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

Leider ist die ungültige Viewstate-Fehlermeldung, die sich im Abschnitt „Einführung“ dieses Artikels befindet, nicht informativ. Die Fehlermeldung wird durch eine Ausnahme verursacht, die generiert wird, wenn der Viewstate verarbeitet wird. Das Problem besteht darin, dass die Ausnahme verschluckt wird und die Details in der Fehlermeldung verloren gehen.

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

Die folgenden Schritte sind ein Beispiel, das den Laufzeitdebugger (Cordbg.exe) verwendet.

  1. Führen Sie an der Eingabeaufforderung den iisreset Befehl aus, um sicherzustellen, dass Sie einen guten Ausgangspunkt haben, und navigieren Sie dann zu einer Seite auf Ihrer Website.

  2. Führen Sie cordbg.exe aus.

  3. Geben Sie <pro>ein, und drücken Sie dann die EINGABETASTE. Eine Liste der verwalteten Prozesse wird angezeigt. Sie sollten entweder den Aspnet_wp.exe oder den W3wp.exe Prozess sehen. Notieren Sie die PID.

  4. Geben Sie ein <PID>.

    Notiz

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

  5. Geben Sie ca e ein, um Cordbg.exe zu instruieren, bei allen Ausnahmen anzuhalten, und führen Sie dann <gto> den Prozess aus.

  6. Wann immer Sie eine Ausnahme erhalten, geben Sie <w> ein, um den Stack zu sehen. Wenn der Stapel eine Viewstate-Ausnahme ist (suchen Sie nach LoadPageStateFromPersistenceMedium im Stapel), kopieren Sie alle Ausnahmen und Stapelinformationen vom Befehlsfenster und speichern Sie dann die Informationen. Diese Informationen können Ihnen dabei helfen, das Problem zu verstehen. Wenn die Ausnahme nicht verknüpft ist, geben Sie <g>.

Versuchen Sie, den Ansichtszustand im Sitzungsspeicher zu speichern.

Standardmäßig wird der Ansichtsstatus mit einem <input type=hidden> Feld gerundet, das an den Browser gesendet wird. Anschließend sendet der Browser das Feld bei der nächsten Anforderung an den Server zurück. In einigen Fällen kann dieser Viewstate umfangreich werden und eine potenzielle Quelle von Problemen sein. Manche Browser können ein so großes ausgeblendetes Feld (und die resultierende Anfrage) nicht verarbeiten, was dazu führen kann, dass der Viewstate abgeschnitten wird. Durch die Verkürzung des "Viewstate" wird eine Fehlermeldung "Viewstate beschädigt" angezeigt. Dieses Verhalten tritt wahrscheinlicher in einfacheren Browsern auf. Dieses Verhalten kann z. B. in einem Browser auf einem PDA auftreten.

Um festzustellen, ob ein solches Problem auftritt, versuchen Sie, den Ansichtsstatus in der Sitzung zu speichern. Im folgenden Beispiel wird die dafür erforderliche Vorgehensweise 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 Recycling des Arbeitsprozesses das Problem verursacht

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 Konto auf Administratorebene ausgeführt.
  • Das validationKey-Attribut des <machineKey>-Elements wird in der Konfigurationsdatei auf AutoGenerate festgelegt.

In diesem Szenario tritt bei der folgenden Prozedur ein Ansichtsstatusfehler auf:

  1. Ein Benutzer bzw. eine Benutzerin durchsucht eine Seite.
  2. Der Arbeitsprozess, in dem die ASP.NET Anwendung gehostet wird, wird neu gestartet.
  3. Der Benutzer bzw. die Benutzerin sendet die Seite zurück.

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

Quellen