Problemen met ongeldige weergavestatus oplossen

In dit artikel worden technieken geïntroduceerd voor foutopsporing en voor het oplossen van problemen met viewstate in Microsoft ASP.NET-toepassingen.

Oorspronkelijke productversie: ASP.NET
Origineel KB-nummer: 829743

Inleiding

Viewstate is een functie in ASP.NET waarmee pagina's de status automatisch kunnen behouden zonder afhankelijk te zijn van de serverstatus (bijvoorbeeld sessiestatus). Problemen met betrekking tot viewstate kunnen echter moeilijk zijn om fouten op te sporen. In de meeste gevallen, wanneer er problemen met viewstate optreden, ontvangt u het volgende foutbericht in de webbrowser, met weinig indicatie van wat het probleem kan veroorzaken:

De viewstate is ongeldig voor deze pagina en is mogelijk beschadigd.

In dit artikel worden enkele technieken beschreven die kunnen worden gebruikt voor foutopsporing en voor het oplossen van problemen met viewstate.

Het kenmerk validationKey instellen als u in een webfarm werkt

In een webfarm kan elke clientaanvraag op elke postback naar een andere computer gaan. Vanwege dit gedrag kunt u het validationKey kenmerk niet ingesteld laten op AutoGenerate in het Machine.config-bestand . In plaats daarvan moet u de waarde van het validationKey kenmerk instellen op een vaste tekenreeks die wordt gedeeld door alle computers in de webfarm.

Dynamisch gegenereerde typen niet opslaan in viewstate in een webfarm

Wanneer ASP.NET bestanden dynamisch compileert, worden de bestanden ingebouwd in assembly's met willekeurige namen (een bestandsnaam kan bijvoorbeeld wordenjp395dun.dll). Als u een webfarm uitvoert, worden dezelfde bestanden gecompileerd in assembly's met verschillende willekeurige namen. Normaal gesproken is dit geen probleem, omdat niemand veronderstellingen doet over die assemblynamen. Maar als u ooit een dynamisch gecompileerd type in viewstate plaatst met behulp van binaire serialisatie, wordt de naam van de assembly opgenomen als onderdeel van de viewstate-gegevens. Wanneer die viewstate later wordt verzonden naar een andere server in de webfarm, kan de viewstate niet worden gedeserialiseerd omdat deze verschillende assemblynamen gebruikt.

De beste oplossing is om binaire serialisatie te vermijden. Binaire serialisatie maakt gebruik van veel resources, zelfs als u dit probleem niet ondervindt. Beperk in plaats daarvan wat u in viewstate plaatst tot een combinatie van matrices, paren, drietallen en eenvoudige typen (bijvoorbeeld tekenreeksen, int en andere typen). System.Web.UI.Pair en System.Web.UI.Triplet zijn eenvoudige wrappertypen die de viewstate-engine efficiënt kan verwerken.

Een alternatieve oplossing om dit probleem te voorkomen, is door de typen die u opslaat in viewstate te verplaatsen naar een vooraf gecompileerde assembly, in uw Bin map of in de Global Assembly cache. Deze oplossing heeft geen betrekking op de prestaties, maar garandeert dat de assembly op alle computers dezelfde naam heeft.

Opmerking

Als u complexe gegevenstypen opslaat in viewstate en dit probleem ondervindt, bevat de aanroepstack-informatie stacks die vergelijkbaar zijn met de volgende:

[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

Het doel van de mac-functie (viewstate machine authentication code) is om het voor clients onmogelijk te maken een aanvraag te verzenden die een schadelijke viewstate bevat. Deze functie is standaard ingeschakeld in de volgende vlag in het Machine.config-bestand .

enableViewStateMac="true"

De eenvoudigste manier om te bepalen of het probleem waarmee u te maken hebt te maken heeft met de MAC-functie, is door de functie uit te schakelen. Wijzig hiervoor de vlag in het Machine.config-bestand in de volgende code.

enableViewStateMac="false"

Als u geen viewstate-fouten meer krijgt, heeft het probleem te maken met de MAC-functie.

Belangrijk

Schakel alleen de mac-functie viewstate uit om het probleem vast te stellen. U moet de weergavestatus MAC niet uitgeschakeld houden om het probleem te omzeilen. Als u dat doet, kunt u beveiligingsgaten introduceren. Zie Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication (Beveiligde ASP.NET-toepassingen bouwen: verificatie, autorisatie en beveiligde communicatie) voor meer informatie.

Als u de functie viewstate MAC uitschakelt en vervolgens viewstate gebruikt voor besturingselementen die geen HTML-codering uitvoeren (bijvoorbeeld een besturingselement Label), kunnen aanvallers knoeien met de viewstate-gegevens en willekeurige gegevens in viewstate plaatsen. Deze willekeurige gegevens worden gedecodeerd en vervolgens gebruikt door besturingselementen wanneer ze de geposte pagina weergeven. Als gevolg hiervan kunnen aanvallers script in de toepassing injecteren, tenzij u de aanval wilt voorkomen. Een aanvaller kan bijvoorbeeld de gegevens decoderen, een script in de gegevens injecteren waar een besturingselement Label zich bevindt en er vervolgens een koppeling naar maken vanaf een website. Iedereen die op de koppeling klikt, zou het slachtoffer zijn van een scriptinjectieaanval die mogelijk zijn verificatiecookies of sessie-id kan stelen. Het script kan een aanvaller ook statusgegevens laten wijzigen voor besturingselementen die gebruikmaken van viewstate en toepassingsspecifieke aanvallen kunnen optreden.

Over het algemeen raadt Microsoft u aan de functie viewstate MAC niet uit te schakelen, tenzij u er zeker van bent dat u viewstate hebt uitgeschakeld voor alle besturingselementen die hun uitvoer niet coderen (bijvoorbeeld DataGrid-besturingselementen, DataList-besturingselementen, Labelbesturingselementen en andere besturingselementen) als HTML hebt uitgeschakeld of dat u hun waarden voor elke aanvraag altijd expliciet instelt op iets dat veilig is.

Bepaal precies welke uitzondering zich voordoet wanneer u het foutbericht ontvangt

Helaas is het ongeldige viewstate-foutbericht dat wordt vermeld in de sectie Inleiding van dit artikel niet informatief. Het foutbericht wordt veroorzaakt doordat er een uitzondering wordt gegenereerd wanneer de weergavestatus wordt verwerkt. Het probleem is dat de uitzondering wordt verbruikt en de details ervan verloren gaan in het foutbericht.

Met behulp van een foutopsporingsprogramma kunt u de oorspronkelijke uitzondering bepalen. Hiervoor moet u een foutopsporingsprogramma koppelen aan het ASP.NET proces (Aspnet_wp.exe of W3wp.exe), en vervolgens instellen dat alle uitzonderingen worden opgevangen. Het foutopsporingsprogramma stopt waarschijnlijk bij een paar uitzonderingen die niet relevant zijn, maar uiteindelijk wordt de uitzondering viewstate bereikt en wordt nuttige informatie weergegeven voor het oplossen van problemen.

De volgende stappen zijn een voorbeeld waarin het Runtime-foutopsporingsprogramma (Cordbg.exe) wordt gebruikt.

  1. Voer bij de opdrachtprompt de iisreset opdracht uit om ervoor te zorgen dat u een goed startpunt hebt en blader vervolgens naar een pagina op uw site.

  2. Uitvoeren cordbg.exe.

  3. Typ <pro>en druk op Enter. Er wordt een lijst met beheerde processen weergegeven. U ziet het Aspnet_wp.exe of het W3wp.exe proces. Noteer de PID.

  4. Typ een <PID>.

    Opmerking

    Vervang PID door de PID die is genoteerd in stap 3.

  5. Typ ca e om Cordbg.exe op te geven dat alle uitzonderingen worden verbroken en typ <gto> vervolgens het proces uitvoeren.

  6. Wanneer u een uitzondering krijgt, typt <w> u om de stack te zien. Als de stack een viewstate-uitzondering is (zoek LoadPageStateFromPersistenceMedium op de stack), kopieert u alle uitzonderingen en de stapelgegevens uit het opdrachtvenster en slaat u de informatie op. Deze informatie kan u helpen het probleem te begrijpen. Als de uitzondering niet gerelateerd is, typt u <g>.

Probeer de viewstate op te slaan in de sessie

Standaard is de viewstate round-triped met een <input type=hidden> veld dat naar de browser wordt verzonden. De browser stuurt het veld vervolgens terug naar de server bij de volgende aanvraag. In sommige gevallen kan deze weergavestatus groot worden en een potentiële bron van problemen zijn. Sommige browsers kunnen zo'n groot verborgen veld (en de resulterende grote aanvraag) niet verwerken en de browsers kunnen de weergavestatus afkappen. Als u de viewstate afkapt, wordt het foutbericht 'viewstate corrupted' weergegeven. Dit gedrag treedt waarschijnlijk op in eenvoudigere browsers. Dit gedrag kan bijvoorbeeld optreden in een browser op een PDA.

Probeer de viewstate op te slaan in de sessie om te bepalen of u een dergelijk probleem ondervindt. In het volgende voorbeeld ziet u hoe u dit doet.

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

Bepalen of het probleem wordt veroorzaakt door recycling van werkprocessen

Neem het volgende scenario:

  • U voert ASP.NET uit onder Microsoft Internet Information Services (IIS) 6.0.
  • De groep van toepassingen wordt uitgevoerd onder een andere identiteit dan het lokale systeemaccount, het netwerkserviceaccount of een account op beheerniveau.
  • Het validationKey kenmerk van het <machineKey> element is ingesteld op AutoGenerate in het configuratiebestand.

In dit scenario zorgt de volgende procedure ervoor dat er een viewstate-fout optreedt:

  1. Een gebruiker bladert door een pagina.
  2. Het werkproces dat als host fungeert voor de ASP.NET toepassing wordt gerecycled.
  3. De gebruiker plaatst de pagina terug.

Als tijdelijke oplossing voor dit scenario gebruikt u een expliciet validationKey kenmerk in het configuratiebestand.

Verwijzingen