Résolution des problèmes d’affichage non valides

par Apurva Joshi

Outils utilisés dans cet utilitaire de résolution des problèmes :

  • N/D

Ce matériel est fourni uniquement à des fins d’information. Microsoft n’offre aucune garantie, expresse ou implicite.

Vue d’ensemble

L’état d’affichage est une fonctionnalité dans ASP.NET qui permet aux pages de conserver automatiquement l’état sans compter sur l’état du serveur (par exemple, l’état de session). Toutefois, les problèmes liés à l’état d’affichage peuvent être difficiles à déboguer. Dans la plupart des cas, lorsque des problèmes d’état d’affichage se produisent, vous recevez le message d’erreur suivant dans le navigateur Web, avec peu d’indication de ce qui peut entraîner le problème :

"The viewstate is invalid for this page and might be corrupted"

Cet article décrit certaines techniques qui peuvent être utilisées pour le débogage et pour résoudre les problèmes liés à l’état d’affichage.

Scénarios et dépannages

Vérifiez que vous ne rencontrez pas de problèmes qui ont été résolus

Un certain nombre de problèmes d’état d’affichage ont été résolus avec les correctifs logiciels ASP.NET 1.0 et les service packs, et ces correctifs font également partie de ASP.NET 1.1. Vérifiez que vous avez appliqué les derniers correctifs avant de résoudre les problèmes de suivi qui ont déjà été résolus. Vous pouvez obtenir les dernières mises à jour de Microsoft .NET Framework à partir du site web Microsoft Developer Network (MSDN) suivant :

https://msdn.microsoft.com/netframework/aa569276.aspx

Définissez l’attribut validationKey si vous exécutez dans une batterie de serveurs web

Dans une batterie de serveurs web, chaque demande cliente peut accéder à un ordinateur différent sur chaque publication. En raison de ce comportement, vous ne pouvez pas laisser l’attribut validationKey défini sur AutoGenerate dans le fichier Machine.config. Au lieu de cela, vous devez définir la valeur de l’attribut validationKey sur une chaîne fixe partagée par toutes les machines de la batterie de serveurs Web.

Pour plus d’informations sur ce problème, cliquez sur le numéro d’article suivant pour afficher l’article dans la Base de connaissances Microsoft :

https://support.microsoft.com/kb/323744

Ne stockez pas les types générés dynamiquement dans l’état d’affichage dans une batterie de serveurs web

Lorsque ASP.NET compile des fichiers dynamiquement, les fichiers sont intégrés dans des assemblys avec des noms essentiellement aléatoires (par exemple, un nom de fichier peut être jp395dun.dll). Si vous exécutez une batterie de serveurs web, les mêmes fichiers sont compilés dans des assemblys avec des noms aléatoires différents. Normalement, ce n’est pas un problème, car personne ne fait d’hypothèses sur ces noms d’assembly. Toutefois, si vous placez un type compilé dynamiquement dans l’état d’affichage à l’aide de la sérialisation binaire, le nom de l’assembly sera inclus dans le cadre des données d’état d’affichage. Lorsque cet état d’affichage est envoyé ultérieurement à un autre serveur dans la batterie de serveurs Web, l’état d’affichage ne peut pas être désérialisé, car il utilise différents noms d’assembly.

La meilleure solution à ce problème consiste à éviter d’utiliser la sérialisation binaire. La sérialisation binaire utilise de nombreuses ressources même si vous ne rencontrez pas ce problème. Au lieu de cela, limitez ce que vous placez dans l’état d’affichage à une combinaison de tableaux, paires, triplets et types simples (par exemple, chaînes, int et autres types). System.Web.UI.Pair et System.Web.UI.Triplet sont des types wrapper simples que le moteur d’état d’affichage peut traiter efficacement.

Une autre solution pour éviter ce problème consiste à déplacer les types que vous stockez dans l’état d’affichage dans un assembly précompilé, soit dans votre dossier Bin, soit dans le Global Assembly Cache. Ce correctif ne traite pas les performances, mais garantit que l’assembly a le même nom sur tous les ordinateurs.

Remarque Si vous stockez des types de données complexes dans l’état d’affichage et rencontrez ce problème, les informations de pile d’appels contiennent des piles similaires aux suivantes :

[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

Déterminer si le problème est lié à la fonctionnalité MAC d’état d’affichage

L’objectif de la fonctionnalité MAC (View State Machine Authentication Code) est de rendre impossible pour les clients d’envoyer une requête qui contient un état d’affichage malveillant. Par défaut, cette fonctionnalité est activée dans l’indicateur suivant dans le fichier Machine.config.

enableViewStateMac="true"

Le moyen le plus simple de déterminer si le problème que vous rencontrez est lié à la fonctionnalité MAC consiste à désactiver la fonctionnalité. Pour ce faire, remplacez l’indicateur dans le fichier Machine.config par le code suivant.

enableViewStateMac="false"

Si vous n’obtenez plus d’erreurs d’état d’affichage, le problème est lié à la fonctionnalité MAC.

Important

Désactivez uniquement la fonctionnalité MAC d’état d’affichage pour vous aider à diagnostiquer le problème. Vous ne devez pas conserver le mac de l’état d’affichage désactivé pour contourner le problème. Si tel est le cas, vous pouvez introduire des trous de sécurité

En règle générale, Microsoft vous recommande de ne pas désactiver la fonctionnalité MAC de l’état d’affichage, sauf si vous êtes complètement confiant que vous avez désactivé l’état d’affichage pour tous les contrôles qui n’encodent pas html encodent leur sortie (par exemple, contrôles DataGrid, contrôles DataList, contrôles Étiquette et autres contrôles) ou que vous définissez toujours explicitement leurs valeurs sur chaque demande sur quelque chose connu pour être sûr.

Déterminez exactement quelle exception se produit lorsque vous recevez le message d’erreur

Malheureusement, le message d’erreur d’état d’affichage non valide mentionné dans la section « Vue d’ensemble » de cet article n’est pas très informatif. Le message d’erreur est généralement dû à une exception levée lorsque l’état d’affichage est traité. Le problème est que l’exception est consommée et que ses détails sont perdus dans le message d’erreur.

À l’aide d’un débogueur, vous pouvez déterminer l’exception d’origine. Pour ce faire, vous devez attacher un débogueur au processus ASP.NET (Aspnet_wp.exe ou W3wp.exe), puis le définir pour intercepter toutes les exceptions. Vous pouvez même configurer l’outil Diagnostics de débogage 1.2 pour capturer des exceptions managées.

Essayez de stocker l’état d’affichage dans la session

Par défaut, l’état d’affichage est aller-retour au moyen d’un <champ INPUT=masqué> qui est envoyé au navigateur. Le navigateur renvoie ensuite le champ au serveur sur la requête suivante. Dans certains cas, cet état d’affichage peut être assez volumineux et être une source potentielle de problèmes. Certains navigateurs ne peuvent pas gérer un champ masqué de grande taille (et la requête volumineuse résultante), et les navigateurs peuvent tronquer l’état d’affichage. La troncation de l’état d’affichage provoque un message d’erreur « état d’affichage endommagé ». Ce comportement est le plus susceptible de se produire dans des navigateurs plus simples. Par exemple, ce comportement peut se produire dans un navigateur sur un PDA.

Pour déterminer si vous rencontrez un tel problème, essayez de stocker l’état d’affichage dans la session. L'exemple suivant illustre la procédure à suivre pour réaliser cette opération.

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

La ligne de code suivante n’est nécessaire que dans ASP.NET 1.0, pour contourner un bogue. Dans ASP.NET 1.1 plus, il n’est pas nécessaire.

<input type=hidden name=__VIEWSTATE>

Déterminer si le problème est dû au recyclage des processus de travail

Considérons le scénario suivant.

  • Vous exécutez ASP.NET sous Microsoft Internet Information Services (IIS) 6.0.
  • Le pool d’applications s’exécute sous une identité autre que le compte système local, le compte de service réseau ou un compte au niveau administratif.
  • L’attribut validationKey de l’élément <MACHINEKEY> est défini sur AutoGenerate dans le fichier de configuration.

Dans ce scénario, la procédure suivante entraîne une erreur d’état d’affichage :

  1. Un utilisateur navigue sur une page.
  2. Processus de travail qui héberge les recyclages de l’application ASP.NET.
  3. L’utilisateur publie la page.

La solution de contournement de ce scénario consiste à utiliser un attribut validationKey explicite dans le fichier de configuration.

Autres ressources