Introduction
Dans un environnement sans état comme une application Web, comprendre le concept d'état de session n'a pas de véritable sens. Néanmoins, une gestion efficace des états est une fonctionnalité indispensable pour la plupart des applications Web. Microsoft ASP.NET, ainsi que de nombreux autres environnements de programmation côté serveur, fournissent une couche d'abstraction qui permet aux applications de stocker des données persistantes par utilisateur et par application.
Il est important de noter que l’état de session d’une application Web correspond aux données que l’application met en cache et récupère lors de différentes requêtes. Une session représente toutes les demandes envoyées par l'utilisateur lorsqu'il est connecté au site, et l'état de la session est la collection de données persistantes générées et consommées par l'utilisateur pendant la session. L'état de chaque session est indépendant les uns des autres et cesse d'exister à la fin de la session utilisateur.
L'état de session n'a aucune correspondance avec aucune des entités logiques qui composent le protocole et la spécification HTTP. Les sessions sont une couche d'abstraction construite par des environnements de développement côté serveur tels que ASP traditionnel et ASP.NET. La manière dont ASP.NET affiche l'état de la session et la manière dont l'état de la session est implémenté en interne dépend de l'infrastructure de la plateforme. Par conséquent, ASP traditionnel et ASP.NET implémentent l'état de session de manière complètement différente, et d'autres améliorations et améliorations sont attendues dans la prochaine version d'ASP.NET.
Cet article explique comment implémenter l'état de session dans ASP.NET 1.1 et comment optimiser la gestion de l'état de session dans les applications Web gérées.
Présentation de l'état de session ASP.NET
L'état de session ne fait pas partie de l'infrastructure HTTP. Autrement dit, il devrait y avoir un composant structurel qui lie l'état de session à chaque requête entrante. L'environnement d'exécution (ASP traditionnel ou ASP.NET) peut accepter des mots-clés comme Session et l'utiliser pour indiquer le bloc de données stocké sur le serveur. Pour résoudre avec succès les appels vers un objet Session, l'environnement d'exécution doit ajouter l'état de session au contexte d'appel de la demande en cours de traitement. La manière dont cela est effectué varie selon les plates-formes, mais elle est fondamentale pour les applications Web avec état.
Dans ASP traditionnel, l'état de session est implémenté sous forme d'objets COM à thread libre contenus dans la bibliothèque asp.dll. (Êtes-vous curieux ? Le CLSID de cet objet est en fait D97A6DA0-A865-11cf-83AF-00A0C90C2BD8.) Cet objet stocke les données organisées sous la forme d'une collection de paires nom/valeur. L'espace réservé « nom » représente la clé utilisée pour récupérer les informations, tandis que l'espace réservé « valeur » représente ce qui est stocké dans l'état de session. Les paires nom/valeur sont regroupées par ID de session afin que chaque utilisateur ne voie que les paires nom/valeur qu'il a créées.
Dans ASP.NET, l'interface de programmation pour l'état de session est presque la même que dans ASP traditionnel. Mais leurs implémentations de base sont complètement différentes. La première est plus flexible, évolutive et possède des capacités de programmation plus puissantes que la seconde. Avant d'examiner l'état de la session ASP.NET, passons brièvement en revue certaines des fonctionnalités structurelles de l'infrastructure de session ASP.NET.
Dans ASP.NET, toute requête HTTP entrante est acheminée via le module HTTP. Chaque module peut filtrer et modifier la grande quantité d'informations véhiculées par la requête. Les informations associées à chaque requête sont appelées « contexte d'appel », qui est représenté par l'objet HttpContext en programmation. Nous ne devons pas considérer le contexte de requête comme un autre conteneur d'informations d'état, bien que la collection Items qu'elle fournit ne soit qu'un conteneur de données. L'objet HttpContext diffère de tous les autres objets d'état (par exemple, Session, Application et Cache) en ce sens qu'il a une durée de vie limitée au-delà du temps requis pour traiter la demande. Lorsqu'une requête passe par une série de modules HTTP enregistrés, son objet HttpContext contiendra une référence à l'objet d'état. Lorsque la requête peut enfin être traitée, le contexte d'appel associé est lié à la session spécifique (Session) et aux objets d'état global (Application et Cache).
Le module HTTP responsable de la définition de l'état de session de chaque utilisateur est SessionStateModule. La structure de ce module est conçue sur la base de l'interface IHttpModule, qui fournit un grand nombre de services liés à l'état de session pour les applications ASP.NET. Comprend la génération d'ID de session, la gestion de session sans cookie, la récupération des données de session auprès de fournisseurs d'état externes et la liaison des données au contexte d'appel de la demande.
Le module HTTP ne stocke pas les données de session en interne. L'état de la session est toujours enregistré dans un composant externe appelé « fournisseur d'état ». Le fournisseur d'état encapsule complètement les données d'état de session et communique avec d'autres parties via les méthodes de l'interface IStateClientManager. Le module HTTP d'état de session appelle des méthodes sur cette interface pour lire et enregistrer l'état de session. ASP.NET 1.1 prend en charge trois fournisseurs d'état différents, comme indiqué dans le tableau 1.
Tableau 1 : Statut Client Fournisseur
Fournisseur Description
Les valeurs de session InProc restent des objets actifs dans la mémoire du processus de travail ASP.NET (aspnet_wp.exe ou w3wp.exe dans Microsoft® Windows Server® 2003). Il s'agit de l'option par défaut.
Les valeurs de session StateServer sont sérialisées et stockées en mémoire dans un processus distinct (aspnet_state.exe). Le processus peut également s'exécuter sur d'autres ordinateurs.
Les valeurs de session SQLServer sont sérialisées et stockées dans les tables Microsoft® SQL Server®. Les instances de SQL Server peuvent s'exécuter localement ou à distance.
Le module HTTP d'état de session lit le fournisseur d'état actuellement sélectionné dans la section <sessionState> du fichier web.config ;
<sessionState mode="InProc | StateServer | SQLServer />;
En fonction de la valeur de l'attribut mode, l'état de la session sera récupéré et stocké dans différents processus à travers différentes étapes. Par défaut, l'état de la session est stocké dans le fichier local Processus de travail ASP.NET. Dans des cas particuliers, il est stocké dans un emplacement dédié de l'objet Cache ASP.NET (non accessible par programme). L'état de session peut également être stocké en externe, même dans un processus distant (par exemple, dans un Windows). Service NT nommé aspnet_state.exe). La troisième option consiste à stocker l'état de la session dans une table de base de données dédiée gérée par SQL Server 2000.
Le module HTTP désérialise la valeur de la session au début de la requête, en faisant des objets dictionnaires. (en fait, les objets de type HttpSessionState) sont ensuite accessibles par programme via la propriété Session exposée par les classes (par exemple, HttpContext et Page). La liaison dure jusqu'à la fin de la requête. Si la requête se termine avec succès, toutes les valeurs d'état sont sérialisées. au fournisseur d'état et disponible pour d'autres demandes.La
figure 1 illustre la communication entre la page ASP.NET demandée et les valeurs de session.Le Code utilisé par chaque page est presque lié à l'attribut Session. le même que celui de l’ASP traditionnel.
Figure 1 : Architecture de l'état de session dans ASP.NET 1.1
La valeur physique de l'état de session est verrouillée pendant le temps nécessaire pour terminer la demande. Ce verrou est géré en interne par le module HTTP et permet de synchroniser l'accès à l'état de la session.
Le module d'état de session instancie le fournisseur d'état de l'application et l'initialise avec les informations lues dans le fichier web.config. Ensuite, chaque fournisseur poursuivra ses propres opérations d'initialisation. Selon le type de fournisseur, ses opérations d'initialisation varieront considérablement. Par exemple, le gestionnaire d'état SQL Server ouvrira une connexion à une base de données donnée, tandis que le gestionnaire hors processus vérifiera le port TCP spécifié. D'un autre côté, le gestionnaire d'état InProc stockera une référence à la fonction de rappel. Cette action est effectuée lorsqu'un élément est supprimé du cache et est utilisée pour déclencher l'événement Session_OnEnd de l'application.
Accès synchrone à l'état de la session
Que se passe-t-il lorsqu'une page Web effectue un appel très simple et intuitif à la propriété Session ? De nombreuses opérations sont effectuées en arrière-plan, comme le montre le code fastidieux suivant :
int siteCount = Convert.ToInt32(Session["Counter"]);
Le code ci-dessus accède en fait à la valeur de session créée par le module HTTP dans la mémoire locale. lit les données d'un fournisseur d'État spécifique (voir Figure 1). Que se passe-t-il si d'autres pages tentent également d'accéder à l'état de la session de manière synchrone ? Dans ce cas, la requête en cours peut cesser de traiter des données incohérentes ou périmées. Pour éviter cela, le module d'état de session implémentera un mécanisme de verrouillage lecteur/écrivain et un accès en file d'attente aux valeurs d'état. Les pages avec des autorisations d'écriture sur l'état de session conserveront le verrou d'écriture pour cette session jusqu'à la fin de la demande.
Une page peut demander une autorisation d'écriture pour l'état de session en définissant la propriété EnableSessionState de la directive @Page sur true. (Il s'agit du paramètre par défaut). Toutefois, une page peut également avoir un accès en lecture seule à l'état de session, par exemple lorsque la propriété EnableSessionState est définie sur ReadOnly. Dans ce cas, le module conservera le verrouillage du lecteur pour cette session jusqu'à la fin de la demande pour cette page. En conséquence, des lectures simultanées auront lieu.
Si une requête de page définit un verrou de lecteur, les autres requêtes simultanées dans la même session ne pourront pas mettre à jour l'état de la session, mais pourront au moins lire. Autrement dit, si une demande en lecture seule est en cours de traitement pour une session, la demande en lecture seule en attente aura une priorité plus élevée qu'une demande nécessitant un accès complet. Si une demande de page définit un verrou d'écriture pour l'état de session, toutes les autres pages seront bloquées, qu'elles souhaitent lire ou écrire du contenu. Par exemple, si deux trames tentent d'écrire dans la session en même temps, une trame doit attendre que l'autre ait terminé avant de pouvoir écrire.
Comparaison des fournisseurs d'état
Par défaut, les applications ASP.NET stockent l'état de session dans la mémoire d'un processus de travail, en particulier dans un emplacement dédié de l'objet Cache. Lorsque le mode InProc est sélectionné, l'état de la session est stocké dans des emplacements au sein de l'objet Cache. Cet emplacement est marqué comme emplacement privé et n’est pas accessible par programme. En d'autres termes, si vous énumérez tous les éléments du cache de données ASP.NET, aucun objet similaire à l'état de session donné ne sera renvoyé. Les objets cache fournissent deux types d'emplacements : les emplacements privés et les emplacements publics. Les programmeurs peuvent ajouter et gérer des emplacements publics, mais les emplacements privés ne peuvent être utilisés que par le système (en particulier, les classes définies dans la partie system.web).
L'état de chaque session active occupe un emplacement dédié dans le cache. L'emplacement est nommé en fonction de l'ID de session et sa valeur est une instance d'une classe interne non déclarée nommée SessionStateItem. Le fournisseur d'état InProc obtient l'ID de session et récupère l'élément correspondant dans le cache. Le contenu de l'objet SessionStateItem est ensuite saisi dans l'objet dictionnaire HttpSessionState et accessible par l'application via la propriété Session. Notez qu'il existe un bogue dans ASP.NET 1.0 qui rend les emplacements privés de l'objet Cache dénombrables par programme. Si vous exécutez le code suivant sous ASP.NET 1.0, vous pourrez énumérer les éléments correspondant aux objets contenus dans chaque état de session actuellement actif.
foreach (élément DictionaryEntry dans le cache)
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
Ce bogue a été résolu dans ASP.NET 1.1 et lorsque vous énumérez le contenu mis en cache, aucun emplacement système ne sera plus répertorié.
InProc est probablement de loin l’option d’accès la plus rapide. Mais gardez à l’esprit que plus les données sont stockées dans une session, plus le serveur Web consomme de la mémoire, ce qui augmente potentiellement le risque de dégradation des performances. Si vous envisagez d'utiliser une solution hors processus, vous devez examiner attentivement les effets possibles de la sérialisation et de la désérialisation. La solution hors processus utilise un service Windows NT (aspnet_state.exe) ou une table SQL Server pour stocker les valeurs de session. Par conséquent, l’état de session reste en dehors du processus de travail ASP.NET et des couches de code supplémentaires sont nécessaires pour sérialiser et désérialiser entre l’état de session et le support de stockage réel. Cela se produit chaque fois qu'une demande est traitée et doit ensuite être optimisée au maximum.
Étant donné que les données de session doivent être copiées du référentiel externe vers le dictionnaire de session local, la requête entraîne une dégradation des performances allant de 15 % (hors processus) à 25 % (SQL Server). Notez que même s’il ne s’agit que d’une estimation approximative, elle devrait être proche de l’impact minimum et l’impact maximum sera bien supérieur à cela. En fait, cette estimation ne prend pas pleinement en compte la complexité des types réellement sauvegardés dans l’état de session.
Dans le scénario de stockage hors processus, l'état de session survit plus longtemps, ce qui rend l'application plus puissante car elle protège contre les pannes de Microsoft® Internet Information Services (IIS) et d'ASP.NET. En séparant l'état de session des applications, vous pouvez également étendre plus facilement les applications existantes dans les architectures Web Farm et Web Garden. De plus, l'état de la session est stocké dans un processus externe, éliminant ainsi le risque de perte de données périodique due aux boucles de processus.
Voici comment utiliser les services Windows NT. Comme mentionné ci-dessus, le service NT est un processus nommé aspnet_state.exe, généralement situé dans le dossier C:WINNTMicrosoft.NETFrameworkv1.1.4322.
Le répertoire réel dépend de la version de Microsoft® .NET Framework que vous exécutez réellement. Avant d'utiliser le serveur d'état, vous devez vous assurer que le service est prêt et exécuté sur l'ordinateur local ou distant utilisé comme périphérique de stockage de session. Le service d'état fait partie et est installé avec ASP.NET, vous n'avez donc pas besoin d'exécuter un programme d'installation supplémentaire. Par défaut, le service d'état n'est pas en cours d'exécution et doit être démarré manuellement. L'application ASP.NET tentera d'établir une connexion au serveur d'état immédiatement après son chargement. Par conséquent, le service doit être prêt et exécuté, sinon une exception HTTP sera levée. L'image suivante montre la boîte de dialogue des propriétés du service.
Figure 2 : boîte de dialogue Propriétés du serveur d'état ASP.NET
Les applications ASP.NET doivent spécifier l'adresse TCP/IP de l'ordinateur sur lequel se trouve le service d'état de session. Les paramètres suivants doivent être saisis dans le fichier web.config de l'application.
<configuration>;
<système.web> ;
<état de session
mode = "Serveur d'état"
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
</configuration>;
L'attribut stateConnectionString contient l'adresse IP de l'ordinateur et le port utilisé pour l'échange de données. L'adresse par défaut de l'ordinateur est 127.0.0.1 (localhost) et le port par défaut est 42424. Vous pouvez également indiquer l'ordinateur par son nom. L'utilisation d'un ordinateur local ou distant est totalement transparente pour le code. Notez que les caractères non-ASCII ne peuvent pas être utilisés dans le nom et que le numéro de port est obligatoire.
Si vous utilisez le stockage de session hors processus, l'état de session existera toujours et sera disponible pour une utilisation future, quel que soit ce qui arrive au processus de travail ASP.NET. Si le service est interrompu, les données seront conservées et automatiquement récupérées lors de la restauration du service. Cependant, si le service du fournisseur de statut s'arrête ou échoue, les données seront perdues. Si vous souhaitez que votre application soit puissante, utilisez le mode SQLServer au lieu du mode StateServer.
<configuration>;
<système.web> ;
<étatdesession
mode="SQLServeur"
sqlConnectionString="server=127.0.0.1;uid=<id utilisateur>;;pwd=<mot de passe>;;" />;
</system.web>;
</configuration>;
Vous pouvez spécifier la chaîne de connexion via l'attribut sqlConnectionString. Notez que la chaîne d'attribut doit contenir l'ID utilisateur, le mot de passe et le nom du serveur. Il ne peut pas contenir de balises telles que Base de données et Catalogue initial, car ces informations portent par défaut un nom fixe. Les identifiants utilisateur et les mots de passe peuvent être remplacés par des paramètres de sécurité intégrés.
Comment créer une base de données ? ASP.NET fournit deux paires de scripts pour configurer l'environnement de base de données. La première paire de scripts est nommée InstallSqlState.sql et UninstallSqlState.sql et se trouve dans le même dossier que le service Session State NT. Ils créent une base de données nommée ASPState et plusieurs procédures stockées. Cependant, les données sont stockées dans la base de données TempDB de la zone de stockage temporaire SQL Server. Cela signifie que si l'ordinateur SQL Server est redémarré, les données de session seront perdues.
Pour contourner cette limitation, utilisez une deuxième paire de scripts. La deuxième paire de scripts est nommée InstallPersistSqlState.sql et UninstallPersistSqlState.sql. Dans ce cas, la base de données ASPState est créée, mais les tables sont créées dans la même base de données et sont également persistantes. Lorsque vous installez la prise en charge de SQL Server pour les sessions, une tâche est également créée pour supprimer les sessions expirées dans la base de données d'état de session. Le travail est nommé ASPState_Job_DeleteExpiredSessions et est toujours en cours d'exécution. Veuillez noter que pour que cette tâche fonctionne correctement, le service SQLServerAgent doit être en cours d'exécution.
Quel que soit le mode que vous choisissez, la façon dont les opérations sur l’état de session sont codées ne change pas. Vous pouvez toujours travailler sur la propriété Session et lire et écrire des valeurs normalement. Toutes les différences de comportement sont traitées à un niveau d'abstraction inférieur. La sérialisation d'état est peut-être la différence la plus importante entre les modes de session.
Sérialisation et désérialisation d'état
Lors de l'utilisation du mode en cours, les objets sont stockés dans l'état de session en tant qu'instances actives de leurs classes respectives. Si aucune sérialisation ni désérialisation réelle ne se produit, cela signifie que vous pouvez réellement stocker n'importe quel objet que vous créez dans la session (y compris les objets qui ne peuvent pas être sérialisés et les objets COM), et y accéder ne sera pas trop coûteux. Si vous choisissez un prestataire étatique hors processus, c'est une autre histoire.
Dans une architecture hors processus, les valeurs de session sont copiées du support de stockage local (base de données AppDomain externe) vers la mémoire de l'AppDomain qui gère la requête. Une couche de sérialisation/désérialisation est nécessaire pour accomplir cette tâche et représente l'un des coûts majeurs des fournisseurs d'état hors processus. Le principal impact de cette situation sur votre code est que seuls les objets sérialisables peuvent être stockés dans le dictionnaire de session.
ASP.NET utilise deux méthodes pour sérialiser et désérialiser les données, selon le type de données impliqué. Pour les types de base, ASP.NET utilise un sérialiseur interne optimisé ; pour les autres types, notamment les objets et les classes définies par l'utilisateur, ASP.NET utilise le formateur binaire .NET. Les types de base incluent les chaînes, les dates et heures, les valeurs booléennes, les octets, les caractères et tous les types numériques. Pour ces types, l’utilisation d’un sérialiseur sur mesure est plus rapide que l’utilisation du formateur binaire .NET commun par défaut.
Le sérialiseur optimisé n’est ni publié ni documenté publiquement. Il s'agit simplement d'un lecteur/enregistreur binaire et utilise une architecture de stockage simple mais efficace. Le sérialiseur utilise la classe BinaryWriter pour écrire une représentation en octets du type, puis écrit une représentation en octets de la valeur correspondant à ce type. Lors de la lecture d'octets sérialisés, la classe extrait d'abord un octet, détecte le type de données à lire, puis appelle la méthode ReadXxx spécifique au type sur la classe BinaryReader.
Notez que la taille des types booléens et numériques est bien connue, mais pas pour les chaînes. Sur le flux de données sous-jacent, la chaîne est toujours préfixée par une longueur fixe (un code entier de 7 bits écrit à la fois), et le lecteur utilise ce fait pour déterminer la taille correcte de la chaîne. La valeur de la date est enregistrée en écrivant uniquement le nombre total de jetons qui composent la date. Par conséquent, pour sérialiser la session, la date doit être de type Int64.
Vous pouvez utiliser la classe BinaryFormatter pour effectuer des opérations de sérialisation sur des objets plus complexes (ainsi que sur des objets personnalisés) à condition que la classe conteneur soit marquée comme sérialisable. Tous les types non basiques sont identifiés par le même ID de type et stockés dans le même flux de données que les types de base. Dans l'ensemble, les opérations de sérialisation peuvent entraîner une dégradation des performances de 15 à 25 %. Notez cependant qu'il s'agit d'une estimation approximative basée sur l'hypothèse que des types de base sont utilisés. Plus les types utilisés sont complexes, plus la surcharge est importante.
Un stockage efficace des données de session est difficile à mettre en œuvre sans une utilisation intensive de types primitifs. Ainsi, au moins en théorie, il est préférable d'utiliser trois emplacements de session pour enregistrer trois propriétés de chaîne différentes d'un objet plutôt que de sérialiser l'objet entier. Mais que se passe-t-il si l’objet que vous souhaitez sérialiser contient 100 propriétés ? Voulez-vous utiliser 100 emplacements ou un seul emplacement ? Dans de nombreux cas, une meilleure approche consiste à convertir un type complexe en plusieurs types plus simples. Cette approche est basée sur des convertisseurs de types. Un « convertisseur de type » est un sérialiseur léger qui renvoie les propriétés clés d'un type sous la forme d'une collection de chaînes. Les convertisseurs de types sont des classes externes liées à une classe de base à l'aide d'attributs. C'est au rédacteur de écrire de décider quelles propriétés sont enregistrées et comment. Les convertisseurs de type sont également utiles pour le stockage ViewState et représentent une méthode de stockage de session plus efficace que les formateurs binaires.
Cycle de vie de session
Un point important concernant la gestion de session ASP.NET est que le cycle de vie de l'objet d'état de session commence uniquement lorsque le premier élément est ajouté au dictionnaire en mémoire. Une session ASP.NET est considérée comme démarrée uniquement après l'exécution de l'extrait de code suivant.
Session["MySlot"] = "Certaines données";
Le dictionnaire Session contient généralement le type Object Pour lire les données à l'envers, la valeur renvoyée doit être convertie en un type plus spécifique.
string data = (string) Session["MySlot"];
Lorsque la page enregistre les données dans la session, la valeur sera chargée dans la classe de dictionnaire spécialement conçue contenue dans la classe HttpSessionState. Le contenu du dictionnaire est chargé dans le fournisseur d'état lorsque la requête en cours de traitement est terminée. Si l'état de la session est vide parce que les données n'ont pas été placées dans le dictionnaire par programme, les données ne seront pas sérialisées sur le support de stockage et, plus important encore, ne seront pas servies dans le cache ASP.NET, SQL Server ou NT State Services. un emplacement pour suivre la session en cours. Ceci est pour des raisons de performances, mais cela a un impact important sur la façon dont les ID de session sont gérés : un nouvel ID de session sera généré pour chaque requête jusqu'à ce que certaines données soient stockées dans le dictionnaire de session.
Lorsqu'il est nécessaire de connecter l'état de session à une requête en cours de traitement, le module HTTP récupère l'ID de session (s'il ne s'agit pas de la requête initiatrice) et le recherche dans le fournisseur d'état configuré. Si aucune donnée n'est renvoyée, le module HTTP génère un nouvel ID de session pour la requête. Cela peut être facilement testé avec la page suivante :
<%@ Page Language="C#" Trace="true" %>;
</html>;
<corps> ;
<form runat="serveur"> ;
<asp:bouton runat="serveur" text="Cliquez" />;
</formulaire>;
</corps>;
</html> ;
Chaque fois que vous cliquez sur le bouton et revenez à la page, un nouvel identifiant de session sera généré et les informations de suivi seront enregistrées.
Figure 3 : Dans une application qui ne stocke pas de données dans un dictionnaire de session, un nouvel ID de session est généré pour chaque requête.
Qu'en est-il de l'événement Session_OnStart ? L'événement sera-t-il également déclenché pour chaque demande ? Si votre application définit un gestionnaire Session_OnStart, l'état de la session est toujours enregistré, même si l'état de la session est vide. Par conséquent, l’ID de session est toujours constant pour toutes les requêtes après la première requête. Utilisez le gestionnaire Session_OnStart uniquement lorsque cela est absolument nécessaire.
Si une session expire ou est abandonnée, son ID de session ne change pas lors du prochain accès à l'application sans état. Il est conçu pour que l'ID de session persiste jusqu'à la fin de la session du navigateur, même si l'état de la session expire. Autrement dit, le même ID de session est toujours utilisé pour représenter plusieurs sessions tant que l'instance du navigateur est la même.
L'événement Session_OnEnd marque la fin d'une session et est utilisé pour exécuter tout code de nettoyage requis pour mettre fin à la session. Notez toutefois que cet événement n'est pris en charge qu'en mode InProc, c'est-à-dire uniquement lorsque les données de session sont stockées dans un processus de travail ASP.NET. Pour que l'événement Session_OnEnd soit déclenché, un état de session doit d'abord exister, ce qui signifie que certaines données doivent être stockées dans l'état de session et qu'au moins une requête doit être complétée.
En mode InProc, l'état de session ajouté au cache en tant qu'éléments reçoit une politique de délai d'expiration variable. L'expiration variable signifie que si un élément n'est pas utilisé dans un certain délai, il sera supprimé. Le délai d'expiration de toute demande traitée pendant cette période sera réinitialisé. L'intervalle de l'élément d'état de session est défini sur le délai d'expiration de la session. La technique utilisée pour réinitialiser le délai d'expiration de l'état de session est très simple et intuitive : le module HTTP de session lit simplement les éléments d'état de session stockés dans le cache ASP.NET. Si la structure interne de l'objet ASP.NET Cache est connue, le module effectuera des calculs pour réinitialiser le délai d'expiration de la variable. Ainsi, lorsque l'élément mis en cache expire, la session a expiré.
Les éléments expirés seront automatiquement supprimés du cache. Le module de session d'état représente également une fonction de rappel de suppression dans le cadre de la politique de délai d'expiration de ce projet. Le cache appellera automatiquement la fonction de suppression, qui déclenchera alors l'événement Session_OnEnd. Si une application effectue une gestion de session via un composant hors processus, l'événement de fin ne sera jamais déclenché.
Sessions sans cookies
Chaque session ASP.NET active est identifiée à l'aide d'une chaîne de 120 bits composée uniquement des caractères autorisés par l'URL. L'ID de session est généré à l'aide d'un fournisseur cryptographique générateur de nombres aléatoires (RNG). Le fournisseur de services renvoie une séquence de 15 nombres générés aléatoirement (15 octets x 8 bits = 120 bits). Le tableau de nombres aléatoires est ensuite mappé sur des caractères d'URL valides et renvoyé sous forme de chaîne.
La chaîne d'ID de session est envoyée au navigateur et renvoyée à l'application serveur de deux manières : en utilisant un cookie (comme dans l'ASP traditionnel) ou une URL modifiée. Par défaut, le module d'état de session créera un cookie HTTP côté client, mais une URL modifiée intégrant la chaîne d'ID de session peut être utilisée (en particulier pour les navigateurs qui ne prennent pas en charge les cookies). La méthode utilisée dépend des paramètres de configuration stockés dans le fichier web.config de l'application. Pour configurer les paramètres de session, vous pouvez utiliser la section <sessionState> et l'attribut Cookieless.
<sessionState cookieless="true|false" />;
Par défaut, l'attribut Cookieless est faux, indiquant que des cookies sont utilisés. En fait, un cookie n'est qu'un fichier texte déposé sur le disque dur du client par une page Web. Dans ASP.NET, un cookie est représenté par une instance de la classe HttpCookie. Généralement, un cookie contient un nom, un ensemble de valeurs et une heure d'expiration. Lorsque l'attribut Cookieless est défini sur false, le module d'état de session créera en fait un cookie nommé ASP.NET_SessionId et y stockera l'ID de session. Le pseudocode suivant montre le processus de création d'un cookie :
HttpCookie sessionCookie ;
sessionCookie = new HttpCookie("ASP.NET_SessionId", sessionID);
sessionCookie.Path = "/";
Le délai d'expiration du cookie de session est très court et le délai d'expiration est mis à jour après la réussite de chaque requête. L'attribut Expires du cookie indique le délai d'expiration du cookie sur le client. Si le cookie de session n'est pas défini explicitement, la propriété Expires a par défaut la valeur DateTime.MinValue, qui est la plus petite unité de temps autorisée par le .NET Framework.
Pour désactiver les cookies de session, définissez l'attribut Cookieless sur true dans le fichier de configuration comme suit :
<configuration> ;
<système.web> ;
<sessionState Cookieless="true" />;
</system.web>;
</configuration> ;
À ce stade, supposons que vous demandez la page à l'URL suivante :
http://www.contoso.com/sample.aspxLe
contenu réel affiché dans la barre d'adresse du navigateur sera différent et contient désormais l'ID de session. , comme suit Affiché dans :
http://www.contoso.com/(5ylg0455mrvws1uz5mmaau45)/sample.aspx
Lors de l'instanciation du module HTTP d'état de session, le module vérifie la valeur de l'attribut Cookieless. Si vrai, redirige la demande (HTTP 302) vers une URL virtuelle modifiée contenant l'ID de session précédant immédiatement le nom de la page. Lorsque la demande sera à nouveau traitée, l'ID de session sera inclus dans la demande. Si une demande est faite pour démarrer une nouvelle session, le module HTTP génère un nouvel ID de session puis redirige la demande. Si la demande est publiée, l'ID de session existe déjà car les publications utilisent des URL relatives.
L'inconvénient de l'utilisation de sessions sans cookies est que l'état de la session est perdu si une URL absolue est appelée. Lors de l'utilisation de cookies, vous pouvez effacer la barre d'adresse, accéder à une autre application, puis revenir à l'application précédente et récupérer la même valeur de session. Si vous faites cela alors que les cookies de session sont désactivés, les données de session seront perdues. Par exemple, le code suivant interrompra la session :
<a runat="server" href="/code/page.aspx">;Click</a>;
Si vous devez utiliser une URL absolue, veuillez utiliser quelques astuces pour modifiez manuellement l’ID de session ajouté à l’URL. Vous pouvez appeler la méthode ApplyAppPathModifier sur la classe HttpResponse.
<a runat="serveur"
href=<% =Response.ApplyAppPathModifier("/code/page.aspx")%>; >;Click</a>;
La méthode ApplyAppPathModifier utilisera une chaîne représentant l'URL et renverra l'URL absolue intégrant les informations de session. Cette technique est particulièrement utile lorsque, par exemple, vous devez rediriger d'une page HTTP vers une page HTTPS.
L'état de sessionrécapitulatif
a été initialement introduit avec l'ASP traditionnel en tant qu'API basée sur un dictionnaire qui permettait aux développeurs de stocker des données personnalisées pendant une session. Dans ASP.NET, l'état de session prend en charge deux fonctionnalités principales : le stockage et le transfert d'ID de session sans cookie, et les fournisseurs d'état où les données de session sont réellement stockées. Pour implémenter ces deux nouvelles fonctionnalités, ASP.NET exploite le module HTTP pour contrôler la liaison entre l'état de la session et le contexte de la requête en cours de traitement.
Dans l'ASP traditionnel, utiliser l'état de session signifie utiliser des cookies. Ce n'est plus le cas dans ASP.NET, puisqu'une architecture sans cookie peut être utilisée. Grâce à la puissance du module HTTP, l'URL demandée peut être décomposée afin qu'elle contienne l'ID de session puis redirigée. Ensuite, le module HTTP extrait l'ID de session de l'URL et l'utilise pour récupérer tout état stocké.
L'état physique d'une session peut être stocké à trois emplacements : mémoire en cours de processus, mémoire hors processus et tables SQL Server. Les données doivent être sérialisées/désérialisées avant de pouvoir être utilisées par l'application. Le module HTTP copie la valeur de session du fournisseur dans la mémoire de l'application au début de la requête. Une fois la demande terminée, le statut modifié est renvoyé au fournisseur. Cette communication de données aura différents degrés d'effets négatifs sur les performances, mais améliorera considérablement la fiabilité et la stabilité et rendra le soutien aux architectures de ferme et de jardin Web plus faciles à mettre en œuvre.