Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    View Cyril Durand's profile on LinkedIn

    hit counters

Optimisation du ViewState - l'enregistrer sur le server via le SessionPageStatePersister

Il y a quelques temps je vous avez expliqué comment modifier la façon dont le viewstate est enregistré, nous avions vu qu'il fallait surcharger les méthodes SavePageStateToPersistenceMedium et LoadPageStateToPersistenceMedium. Je viens de découvrir que l'on peut faire encore mieux, il est également possible de surcharger la propriété PageStatePersister de l'objet Page.

Cette propriété de type PageStatePersister est une classe abstraite qui nécessite la surcharge de deux méthodes : Save et Load qui sauvegarde ou restaure l'état des contrôles. Il existe deux implémentations dans ASP.net, HiddenFieldPageStatePersister et SessionPageStatePersister. Par défaut le HiddenFieldPageStatePersister est utilisé. C'est lui qui est responsable de l'émission d'un champ caché "__VIEWSTATE" qui pose bien des problèmes.

Avec ASP.net Ajax, on utilise de plus en plus des UpdatePanel, or le fonctionnement d'un UpdatePanel est exactement le même qu'un postback : le viewstate transite entre les appels ! Dans certains cas cela peut être une cause de problème de performance, il peut alors être intéressant de stocker cet état au niveau du serveur dans la session. De plus, il semble que si l'on utilise massivement le viewstate, le CPU et la mémoire s'affole. Pour sauvegarder l'état de la page dans le session on peut utiliser le SessionPageStatePersister. Deux possibilités :

  • Vous disposez d'une classe Page abstraite commune à toutes vos pages (ce que je recommande). Il faut alors surcharger la propriété PageStatePersister de la sorte :

protected override PageStatePersister PageStatePersister { get { return new SessionPageStatePersister(this.Page); } }

  • Vous ne disposez pas d'une classe Page abstraite. Il vous faut alors utiliser un Control Adapter :

public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter { public override PageStatePersister GetStatePersister() { return new SessionPageStatePersister(Page); } }

Puis dans votre fichier .browser rajouter votre ControlAdapter :
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.Page" adapterType="CS.CSSFriendly.MyPageAdapter" />

Par défaut, le ControlState est encore stocké dans le champ caché __ViewState pour modifier ce comportement il faut modifier le fichier .browser

<browsers> <browser refID="Default"> <capabilities> <capability name="requiresControlStateInSession" value="true" /> </capabilities>

Le ControlState est généralement très petit et contient l'état d'un contrôle même si l'on met EnableViewState à false : Control State vs. View State Example (MSDN)

[UPDATE] Ashi4 m'a donné une autre solution pour modifier ce comportement directement au niveau du web.config. Vu ici : ViewState, ControlState et PageStatePersister

<configuration>
   
<system.web>
       
<browserCaps>
           
<case>RequiresControlStateInSession=true</case>
       
</browserCaps>
   
</system.web>
</configuration>

[/UPDATE]

Le champ "__ViewState" restera malgré tout toujours présent. Pourquoi ? En fait, le viewstate ne contiendra plus que la clé de l'état dans la session, il pésera moins de 100 octets. Si vous ne voulez plus du champ ViewState vous pouvez toujours modifier ce comportement en surchargeant les méthodes SavePageStateToPersistenceMedium et LoadPageStateToPersistenceMedium.

Attention : Changer ce paramètre n'est pas une choses anodine ! En utilisant le SessionPageStatePersister vous allez considérablement augmenter les ressources utilisé par votre serveur, en effet toutes les requêtes vont alors enregistrer l'état en session, y compris les requêtes qui ne gèrent pas les sessions (bot, refus des cookies, ...) Il est alors bon de bien customiser son fichier .browser pour utiliser le SessionPageStatePersister avec les clients/pages qui nécessitent l'utilisation du SessionStatePersister.

L'avantages d'utiliser un champ caché et au niveau de la gestion de l'historique. En effet lorsque l'on va sur la page précédente, on retrouve le bon viewstate. Pour gérer ce cas là, le SessionPageStatePersister utilise une Queue qui contient par défaut les 9 derniers états en session. Pour modifier cette valeur il faut modifier le web.config de la sorte :

<configuration> <system.web> <sessionPageState historySize="9"/>

Remarque : Bien sur, mettre l'état des contrôles sur le serveur est une solution à bien des problèmes, mais il est également nécessaire de désactiver le viewstate là où il n'est pas indispensable. Pour cela il faut bien comprendre le fonctionnement de celui-ci. L'article TRULY Understanding ViewState vous sera très utile.

PS : Je n'ai pas encore utilisé cette solution dans un vrai site web, mais je vais l'utiliser assez rapidement. Si vous avez des retour d'experience, n'hésitez pas à les partager :)

D'autres en parlent :

Posted: mercredi 2 janvier 2008 15:23 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

Ashi4 a dit :

j'étais tomber sur cette classe il y a quelque temps...

Public Class SpecialPage

   Inherits System.Web.UI.Page

   Private _PageStatePersister As PageStatePersister

   Protected Overloads Overrides ReadOnly Property PageStatePersister() As System.Web.UI.PageStatePersister

       Get

           If _PageStatePersister Is Nothing Then

               _PageStatePersister = New SessionPageStatePersister(Me)

           End If

           Return _PageStatePersister

       End Get

   End Property

End Class

et les pages hérite non plus de page mais de specialpage. Tout le viewstat ce retrouve alors sur le server.

les explications sont là :

http://controlbreak.free.fr/index.php/tag/ViewState

# janvier 2, 2008 16:03

cyril a dit :

Vi c'est la version VB de ce que j'explique avec la classe Page abstraite :-)

Je viens de mettre à jour mon post en expliquant comment modifier la persistance du ControlState au niveau du web.config.

As tu des retour particuliers sur le SessionPageStatePersister ? Je pense réimplémenter mon propre PageStatePersister pour désactiver le mode Session aux bots pour éviter de trop surcharger le serveur.

# janvier 2, 2008 16:48

Ashi4 a dit :

bah non étonnament tout marche bien, par contre, j'ai pas fait de test avec pleins de visiteur, je travail uniquement sur un intranet, et j'ai un serveur qui peut très largement prendre les sessions de mes utilisateurs...

donc pour ma part, je peux vous dire que dans le cadre d'un intranet ça marche très bien et ça améliore les temps de réponse. mais je ne m'avance pas plus.

# janvier 2, 2008 17:05
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Disparition de variables de session PHP après une redirection ? par MadMatt le il y a 9 heures et 35 minutes

- [MOSS 2007] Publier ses formulaires InfoPath via feature par Adrien Siffermann le il y a 12 heures et 42 minutes

- Imagine Cup 2008 - Paris - Les résultats par TheSaib .NET blog le il y a 14 heures et 4 minutes

- L'Egypte accueille Imagine Cup 2009 par Code is poetry le il y a 14 heures et 16 minutes

- PowerShell : Mise en ligne de fonctions intéressantes pour SharePoint par Blog Technique de Romelard Fabrice le il y a 15 heures et 23 minutes

- Raccourcis clavier et CRM 4 par Clark, C#, MSCRM, SBS le il y a 19 heures et 29 minutes

- [Silverlight] Comment échanger des données entre une application Silverlight et une page ASP.NET via cookies ? par Thomas Lebrun le il y a 20 heures et 5 minutes

- SharePoint 2007 : Trouver les fichiers CheckOut dans une librairie de document par Philippe Sentenac [MVP SharePoint] le il y a 22 heures et 33 minutes

- [Open XML] Travailler avec Open XML : Linq To XML (Partie 2 - Requêtes/XPath) par Julien Chable le 07-08-2008, 02:05

- [Open XML] Travailler avec Open XML : Linq To XML (Partie 1 - Namespace) par Julien Chable le 07-08-2008, 00:44