web-dev-qa-db-fra.com

Existe-t-il une meilleure pratique et une alternative recommandée aux variables de session dans MVC

D'accord, donc tout d'abord avant que quiconque essaie de déterminer qu'il s'agit d'une question "en double"; J'ai passé en revue la plupart des articles sur SO concernant des questions similaires, mais même en combinant tout ce qui a été dit, je suis toujours quelque peu confronté à un dilemme quant au définitif ou peut-être devrais-je dire un accord unanime sur cette.

Je peux cependant dire que j'ai (sur la base des postes) déterminé de manière concluante que la réponse est basée sur la portée de l'exigence. Mais même en tenant compte de cela, les opinions semblent trop diverses pour que je puisse prendre une décision quant à la façon dont je dois gérer cela.

Mon exigence immédiate est que je dois conserver les données variables d'un contrôleur sur plusieurs vues. Plus précisément, j'ai un contrôleur et une vue correspondante qui gère le nombre d'articles du panier et je voudrais conserver ces données sur plusieurs vues. Je pense que la vue _layout est le choix le plus logique pour cela.

Maintenant, j'ai réussi cette tâche en affectant la valeur à une variable de session qui est récupérée à partir de ma vue _layout; ainsi, même lorsque l'utilisateur devait naviguer n'importe où dans le site, le nombre d'articles dans le panier persiste jusqu'à ce qu'il quitte le site ou termine la commande; auquel cas la variable sera effacée dans le code.

Les articles que j'ai lus semblaient biaisés soit pour rester à l'écart des variables de session en faveur des cookies et pour stocker des données dans une base de données; ou en déclarant que dans le but pour lequel je propose de les utiliser, les variables de session sont parfaitement adaptées.

L'autre chose que j'ai lue suggère que les variables de session peuvent potentiellement nuire aux performances globales s'il y a un trafic élevé sur le site puisque les informations sont stockées sur le serveur.

Personnellement, je ne peux pas justifier le stockage de ce type d'informations dans une base de données et par la suite frapper la base de données car j'imagine que cela pourrait également affecter les performances du site et semble un peu exagéré pour le stockage de données temporaires. TempData, ViewData et ViewBag ne fonctionnent pas pour conserver les données, ce ne sont donc pas des choix logiques pour l'exigence IMO.

S'il existe une autre alternative bien adaptée à la variable Session (qui fonctionne pour moi), je voudrais savoir de quoi il s'agit.

2 messages qui semblent contradictoires dans l'effort de fournir les meilleures recommandations me laissent un peu confus.

Inconvénients: Est-ce une bonne pratique pour éviter d'utiliser l'état de session dans ASP.NET MVC? Si oui, pourquoi et comment?

Avantages: Vous pouvez toujours utiliser des variables de session dans ASP.NET mvc, ou existe-t-il une meilleure alternative pour certaines choses (comme un panier)

Semble que cette question (bien que présentée dans de nombreuses variantes différentes) n'a pas de réponse définitive que je peux conclure.

S'il existe un moyen plus préférable d'accomplir cela sans surpuissance, c'est la réponse que je recherche.

J'ai lu quelque part l'utilisation des filtres MVC en tandem avec la section de démarrage de l'application Global.ascx, mais cela ne semble pas approprié autant pour les variables définies au niveau du contrôleur que pour les variables statiques.

Quelqu'un peut-il écraser (faute d'un meilleur mot) les nombreuses opinions diverses sur le sujet et peut-être fournir une réponse plus définitive à la question? Je suis sûr que les diverses opinions ont leur place et je ne cherche pas à les discréditer. Mais avoir une réponse définitive et peut-être unanime serait mieux; alors je pourrais trier les autres messages pour déterminer ce qui est le mieux pour mon application.

Bien sûr, si cette question n'a pas de réponse définitive; dites-le moi et j'essaierai de tirer ma propre réponse des autres articles.

Merci

================================================== =========

RÉPONSE ACTUALISÉE AUX RÉPONSES FOURNIES

La mise en cache et les cookies semblent être une préférence générale dans les réponses, mais j'ai également noté la déclaration selon laquelle la mise en cache n'est pas un candidat idéal à utiliser sur plusieurs serveurs Web, car la synchronisation peut être un problème potentiel.

En accordant un crédit à Tim, il est indiqué que le stockage de la base de données est optimisé et que les utilisateurs ont la possibilité de revenir plus tard et de continuer là où ils se sont arrêtés.

C'est un excellent point, mais garder une vision prospective des probabilités; c'est probablement raisonnable étant donné que certains utilisateurs peuvent ne pas revenir en laissant des données inutiles dans la base de données.

Donc, pour garder la base de données optimisée et propre (qui "pour moi" est tout aussi pertinente), il faudrait implémenter une tâche de maintenance pour expirer automatiquement ces enregistrements en fonction d'un seuil de temps défini pour tenir compte de ces circonstances. Bien qu'une tâche de maintenance ne soit pas une option incontestable, je pense toujours que cela ajoute un peu plus de travail à la tâche simplement dans le but de servir de stockage temporaire.

Néanmoins, je respecte la recommandation de Tim et je crois qu'elle mérite d'être contrée dans une certaine mesure; qu'une base de données ne semble pas être une option viable pour stocker des données temporaires; Je pense donc que le compromis serait de stocker les données dans une base de données (compte tenu du scénario d'un panier ou similaire) peut-être après un paiement. De cette façon, comme vous l'avez indiqué précédemment, les données peuvent être suivies de manière persistante lors des visites ultérieures, vous avez donc un enregistrement des transactions. Mais plus important encore, ce serait les données de ces transactions ayant une réelle pertinence qui persisteraient dans la base de données.

Il a également été déclaré que, bien que la session soit plus rapide que la base de données; mais en dépit d'avoir ses mises en garde qui peuvent dans une certaine mesure être atténuées par d'autres mécanismes tels que l'exploitation de l'attribut SessionStateBehavior, servant uniquement d'exemple.

MAIS ... Je pense qu'Erik a un peu ramené le clou avec l'effet Dunning-Kruger. Bien que, d'après le contenu et les explications des réponses proposées données ici; Je doute sérieusement que l'expertise des personnes qui ont répondu est de quelque manière que ce soit douteuse. Néanmoins, j'ai tendance à être d'accord sur le fait que l'obtention d'une opinion unanime peut être quelque peu supérieure à une attente raisonnable de ma part.

Ce que je recherchais plus précisément, c'était un consensus général pour une technique qui pourrait accueillir confortablement un nombre divers de scénarios. En d'autres termes, quelque chose qui s'adapterait non seulement à mon scénario particulier, mais fournirait également l'élément d'évolutivité à des environnements plus vastes avec un trafic potentiellement plus lourd. De cette façon, un changement dans la programmation serait soit atténué, soit au mieux minimal.

==================================================

Résumé basé sur les commentaires:

  1. Les variables de session semblent s'adapter à des scénarios de cas plus petits et, le cas échéant, mais elles peuvent présenter des problèmes de persistance parmi d'autres divergences notables, comme indiqué très attentivement par Erik. Donc, cette option ne correspondra évidemment pas à un modèle évolutif.

  2. La mise en cache est préférable aux variables de session mais encore une fois pas nécessairement la "meilleure" option évolutive en raison, entre autres, des complexités de synchronisation potentielles dans les environnements de batterie de serveurs Web, comme indiqué précédemment. Mais une option néanmoins.

  3. Le stockage de la base de données est évolutif, mais dans le but intentionnel du stockage volatile temporaire, ce n'est probablement pas l'option la plus élégante du point de vue de la base de données car cela nécessiterait un nettoyage périodique. Personnellement, ayant une base solide dans les concepts de base de données au début de ma carrière, cela ne sera probablement pas quelque chose avec lequel de nombreux développeurs seront probablement d'accord; mais l'utilisation de la base de données à cette fin peut suffire pour le développement Web du point de vue des programmeurs; cependant, du point de vue du développement DAL et DB, cela (pour moi) a le potentiel de mandater une tâche DB supplémentaire pour appliquer un backend efficace.

  4. Les cookies semblent être une bonne option ayant les éléments "souhaitables" combinés des variables de session et de la mise en cache.

==================================================

CONCLUSION

Basé sur les réponses; Je pense que les COOKIES et la mise en cache semblent être des propositions généralement bien arrondies pour les meilleures pratiques à tous les niveaux en combinaison avec le stockage de la base de données lorsqu'une persistance continue est requise après coup; comme potentiellement de bons candidats pour l'évolutivité de ceux présentés.

Le choix ultime entre les 2 semble reposer sur la quantité et le type de données nécessitant un stockage (par exemple, sensibles ou non sensibles et s'il y a ou non une préoccupation que le client puisse modifier les données de leur côté); en plus des considérations spéciales pour les COOKIES dans le fait qu'ils peuvent être désactivés par les clients.

De toute évidence, il n'y a pas de solution unique, comme cela a été clairement indiqué et conclu à partir des réponses fournies, mais en termes d'évolutivité; Je peux me tromper mais ceux-ci semblent être les MEILLEURS choix disponibles.

Parce que toutes les réponses sont bonnes; Je vais assez créditer tous les messages comme utiles et accepter la réponse d'Erik comme une solution évolutive globale bien arrondie. J'aimerais pouvoir sélectionner plus d'une réponse acceptée car je pense que la réponse de Tim était également très bien présentée et concise.

La réponse de Gupta était également bonne, mais je voulais plus de détails sur la réponse proposée et non une répétition des messages précédents.

Merci les gars!

45
Mark

Vous n'obtiendrez jamais d'opinion unanime sur quoi que ce soit dans un grand groupe de personnes. C'est juste la nature humaine. Une partie de cela découle de Dunning-Kruger Effect qui stipule que moins quelqu'un en sait sur un sujet, plus il est probable qu'il surestime son expertise dans ce sujet. En d'autres termes, beaucoup de gens pensent qu'ils savent quelque chose, mais seulement parce qu'ils ne savent pas qu'ils ne le savent pas. Une partie de cela est simplement que les gens ont des expériences différentes, et certains n'ont trouvé aucun problème avec la session, tandis que d'autres l'ont dans diverses situations, ou vice versa ...

Donc, pour sauvegarder votre recherche, ce qui suggère que la réponse dépend fortement des exigences, nous devons comprendre quelles sont vos exigences. S'il s'agit d'un site à fort trafic, avec des serveurs à charge équilibrée dans une batterie de serveurs Web, restez le plus loin possible de la session. Bien sûr, il est possible de partager la session de différentes manières dans un environnement de batterie de serveurs (serveur de session, serveur de cache de distribution, etc.), mais éviter la session sera presque toujours plus rapide si vous pouvez l'aider.

Si votre site est un serveur unique et qu'il est peu probable qu'il se développe au-delà. Et vos modèles de trafic sont relativement faibles, alors la session peut être une option utile. Cependant, vous devez toujours savoir que la session n'est pas un stockage fiable et peut disparaître à tout moment. Si le pool d'applications est recyclé, la session a disparu. Si une exception non interceptée se propage jusqu'au processus de travail, la session peut être terminée. Si IIS pense qu'il n'y a pas assez de mémoire, votre session peut avoir disparu, quelles que soient les valeurs de délai d'attente configurées. Vous ne pouvez pas toujours obtenir une notification fiable de la fin d'une session, car les sessions terminées ne le font pas déclenchez l'événement Session_End.

Un autre problème est que la session est sérialisée. En d'autres termes, IIS empêche plus d'un thread d'écrire dans la session à la fois, et il le fait souvent en verrouillant la session pendant qu'un thread est en cours d'exécution s'il n'a pas choisi d'écrire en écriture verrouillage de session. Cela peut entraîner de graves problèmes dans certains cas, et simplement de mauvaises performances dans d'autres. Vous pouvez atténuer cela en marquant diverses méthodes avec un attribut de session en lecture seule si vous n'allez pas le modifier dans cette méthode.

En fin de compte, si vous choisissez d'utiliser la session, essayez de ne l'utiliser que pour de petites choses de courte durée si possible, et si ce n'est pas possible, construisez de manière à "régénérer" les données si la session est perdue. Par exemple, en utilisant votre nombre d'articles dans l'exemple de panier, vous pouvez écrire une méthode qui vérifie d'abord si la valeur est là, et sinon elle sort et la charge depuis la base de données. Utilisez toujours cette méthode pour accéder à la variable, plutôt que d'y accéder directement à partir de la session ... de cette façon, si la session est perdue, elle la rechargera simplement.

Cependant, cela étant dit ... Pour le nombre d'articles dans un panier, je préfère généralement utiliser un cookie pour ces informations, car les cookies sont transmis à la page à chaque chargement de toute façon, et il s'agit d'une petite unité de données discrète . Préférez généralement Session pour les données sensibles que vous souhaitez empêcher l'utilisateur de pouvoir modifier. Le nombre d'articles dans le panier ne correspond tout simplement pas à cette règle.

25

Quand

Les bases de données sont hautement optimisées. Une valeur simple comme le nombre de paniers est un bon candidat pour la mise en cache par la base de données et (espérons-le) peu coûteuse à calculer. Ce n'est peut-être pas un problème.

Cependant, si vous avez exclu d'autres mécanismes, les petites valeurs utilisateur par utilisateur sont des candidats viables pour la session.

Cache convient aux valeurs à l'échelle du site ou aux valeurs spécifiques à l'utilisateur avec des clés uniques. Cependant, la synchronisation des caches sur plusieurs serveurs Web peut être difficile. L'état de session hors processus restera synchronisé car il est stocké dans un seul emplacement (base de données ou serveur d'état).

Bien sûr, il existe de nombreuses alternatives de mise en cache tierces avec diverses options pour les garder synchronisées.

Peu importe où le décompte est temporairement stocké, je suis d'avis que les paniers d'achat eux-mêmes devraient être stockés dans la base de données afin que les utilisateurs aient la possibilité de revenir plus tard et de continuer là où ils se sont arrêtés.

Performance

Si vous utilisez un état de session hors processus (par exemple dans un environnement à charge équilibrée et/ou pour rendre la session plus durable), il frappera une base de données ou appellera un service hors processus, mais l'appel est relativement bon marché, sauf si vous sérialisez des graphiques d'objets volumineux.

La session est chargée une fois par demande. L'accès en lecture suivant est très rapide.

L'écriture dans la session peut nuire aux performances, même en l'absence de charge. Pourquoi? la plupart des applications modernes utilisent des appels asynchrones et lorsque plusieurs appels asynchrones frappent un gestionnaire HTTP (page, contrôleur, etc.) qui lit/écrit la session, ASP.Net verrouille la session pour sérialiser l'accès. Pour éviter cela, vous pouvez décorer vos contrôleurs avec [SessionState( SessionStateBehavior.ReadOnly )]

Conception

Maintenant, j'ai réussi cette tâche en affectant la valeur à une variable de session qui est récupérée à partir de ma vue _layout;

Cela semble mélanger les préoccupations, c'est-à-dire avoir une vue consciente du mécanisme de stockage sous-jacent. D'un point de vue puriste, je définirais cette valeur sur un modèle de vue ou au moins la mettrais dans le ViewBag. D'un point de vue pratique, une ou deux valeurs récupérées de cette manière ne feront probablement rien de mal, mais attention à ne pas la laisser grandir encore plus.

J'ai lu quelque part l'utilisation des filtres MVC en tandem avec la section de démarrage de l'application Global.ascx, mais cela ne semble pas approprié autant pour les variables définies au niveau du contrôleur que pour les variables statiques.

Les variables statiques ont des utilisations parfaitement légitimes, mais vous devez les comprendre à fond ou risquer de graves problèmes.

Voir mes réponses concernant les variables statiques dans ASP.Net:

10
Tim Medora

Session alternative dans différentes perspectives: -

Lorsque vous conservez quelque chose en session, cela rompt la règle principale dans ASP.NET MVC. Vous pouvez utiliser ces options comme alternative à la session.

Si votre session asp.net (MVC) fait de la boxe unboxing sur l'objet alors cela fait un peu de charge sur le serveur. Essayez cette idée

  1. Caching: - Il est préférable de stocker une liste ou quelque chose comme de grandes données en session dans Caching. Vous avez le contrôle sur le moment où vous souhaitez qu'il expire plutôt que sur la session utilisateur.

  2. Si votre application dépend des données JSON/Ajax, vous pouvez utiliser une sorte de fonctionnalité fournie en html5 (comme WebSQL, IndexDB). il n'utilisera pas le cookie afin que vous puissiez économiser une charge de travail sur le serveur.

3
Anirudha Gupta