Question

Je souhaite enregistrer l'état " état " certaines actions exécutées par l’utilisateur dans une série de formulaires Web ASP.Net différents. Quels sont mes choix pour l’état persistant et quels sont les avantages / inconvénients de chaque solution?

J'utilisais des objets Session et des méthodes d'assistance pour taper fortement les objets:

    public static Account GetCurrentAccount(HttpSessionState session)
    {
        return (Account)session[ACCOUNT];
    }

    public static void SetCurrentAccount(Account obj, HttpSessionState session)
    {
        session[ACCOUNT] = obj;
    }

De nombreuses sources m'ont dit que "Session is evil", c'est donc la cause première de cette question. Je veux savoir ce que vous pensez des "meilleures pratiques" et pourquoi.

Était-ce utile?

La solution

Il n'y a rien de mal par nature à l'état de session.

Il y a plusieurs choses à garder à l’esprit qui pourraient vous mordre:

  1. Si l'utilisateur appuie sur le bouton Précédent du navigateur, vous revenez à la page précédente, mais l'état de votre session n'est pas rétabli. Votre compte courant ne correspond donc peut-être pas à ce qu'il était à l'origine sur la page.
  2. Les processus ASP.NET peuvent être recyclés par IIS. Lorsque cela se produit, votre prochaine demande démarrera un nouveau processus. Si vous utilisez l'état de session en cours de traitement, la valeur par défaut sera: - (
  3. La session peut également expirer avec le même résultat si l'utilisateur n'est pas actif pendant un certain temps. La valeur par défaut est 20 minutes alors un bon déjeuner le fera.
  4. Pour utiliser l'état de session hors processus, tous les objets stockés dans l'état de session doivent être sérialisables.
  5. Si l'utilisateur ouvre une deuxième fenêtre de navigateur, il s'attend à disposer d'une deuxième application distincte, mais l'état de la session sera probablement partagé entre deux. Donc, changer le compte courant dans une fenêtre du navigateur aura le même effet dans la seconde.

Autres conseils

Vos deux choix pour stocker temporairement les données de formulaire sont, d’une part, de stocker les informations de chaque formulaire dans des variables d’état de session et, d’autre part, de les transmettre avec des paramètres d’URL. L'utilisation de cookies en tant que troisième option potentielle n'est tout simplement pas réalisable pour la simple raison que bon nombre de vos visiteurs risquent de voir les cookies désactivés (ceci n'affecte toutefois pas les cookies de session). De plus, je suppose, en raison de la nature de votre question, que vous ne souhaitez pas stocker ces informations dans une table de base de données tant qu’elles ne sont pas entièrement validées.

L’utilisation de variable (s) de session est la solution classique à ce problème, mais elle présente quelques inconvénients. Parmi celles-ci, notons (1) la mémoire vive du serveur pouvant être utilisée par de grandes quantités de données si vous utilisez la gestion de session inproc, (2) le partage de variables de session entre plusieurs serveurs d'une batterie de serveurs nécessite des considérations supplémentaires, et (3) une application conçue par des professionnels doit: Protégez-vous contre l'expiration de la session (ne convertissez pas simplement une variable de session et utilisez-la - si la session a expiré, la conversion générera une erreur). Cependant, pour la grande majorité des applications, les variables de session sont incontestablement la voie à suivre.

L'alternative consiste à transmettre les informations de chaque formulaire dans l'URL. Le principal problème de cette approche est qu’il faut faire très attention à la "transmission". information. Par exemple, si vous collectez des informations sur quatre pages, vous devez collecter des informations dans la première, puis les transférer dans l'URL de la deuxième page, où vous devez les stocker dans l'état d'affichage de cette page. Ensuite, lors de l'appel de la troisième page, vous collecterez les données de formulaire à partir de la deuxième page, des variables viewstate, et encoderez les deux dans l'URL, etc. Si vous avez cinq pages ou plus, ou si le visiteur naviguera sur le site, vous Je vais avoir un vrai désordre sur vos mains. N'oubliez pas non plus que toutes les informations devront A) être sérialisées en une chaîne sécurisée pour les URL et B) codées de manière à empêcher les piratages simples basés sur des URL (par exemple, si vous mettez le prix en texte clair et le transmettez) le long, quelqu'un pourrait changer le prix). Notez que vous pouvez réduire certains de ces problèmes en créant une sorte de " gestionnaire de session " et demandez-lui de gérer les chaînes d'URL pour vous, mais vous devez rester extrêmement sensible à la possibilité qu'un lien donné puisse effacer toute la session de quelqu'un s'il n'est pas géré correctement.

En fin de compte, j’utilise les variables d’URL uniquement pour transmettre des données très limitées d’une page à l’autre (par exemple, l’ID d’un élément codé dans un lien vers cet élément).

Supposons donc que vous gériez effectivement les données d'un utilisateur à l'aide de la fonctionnalité Sessions intégrée. Pourquoi quelqu'un vous dira-t-il que "la session est un mal"? Eh bien, outre les considérations relatives à la charge de mémoire, à la batterie de serveurs et à l’expiration présentées ci-dessus, la critique principale des variables de session est qu’elles sont, en réalité, des variables non typées.

Heureusement, une utilisation prudente des variables de session peut éviter les problèmes de mémoire (les gros éléments doivent de toute façon être conservés dans la base de données) et si vous exécutez un site suffisamment grand pour nécessiter une batterie de serveurs, de nombreux mécanismes sont disponibles pour le partage de l'état. dans ASP.NET (conseil: vous n’utiliserez pas de stockage inproc).

Pour éviter essentiellement tous les inconvénients de la session, il est recommandé d'implémenter un objet pour stocker vos données de session, ainsi que des fonctionnalités simples de gestion des objets de session. Puis construisez-les en un descendant de la classe Page et utilisez cette classe en descendant pour toutes vos pages. Il est alors simple d'accéder à vos données de session via la classe de page en tant qu'ensemble de valeurs fortement typées. Notez que les champs de votre objet vous permettront d'accéder à chacune de vos "variables de session". de manière fortement typée (par exemple, un champ par variable).

Faites-moi savoir s'il s'agit d'une tâche simple pour vous ou si vous souhaitez un exemple de code!

Pour autant que je sache, Session est le moyen prévu pour stocker ces informations. N'oubliez pas que l'état de session est généralement stocké dans le processus par défaut. Si vous avez plusieurs serveurs Web ou s'il y a un redémarrage d'IIS, vous perdez l'état de la session. Ce problème peut être résolu à l'aide d'un service d'état ASP.NET ou même d'une base de données SQL pour stocker des sessions. Cela garantit que les utilisateurs récupèrent leur session, même s'ils sont redirigés vers un autre serveur Web ou en cas de recyclage du processus de travail.

L’une des raisons de sa sinistre réputation est que les développeurs pressés l’utilisent avec des littéraux de chaîne dans le code de l’UI (plutôt qu’une classe d’aide comme la vôtre) comme clés d’éléments, et aboutissent à un gros sac d’états invraisemblables. Une sorte de wrapper est une exigence d'entrée de gamme pour une utilisation de session non perverse.

En ce qui concerne "La session est diabolique" ... si vous développiez en ASP classique, je suis d’accord, mais ASP.NET/IIS fait un bien meilleur travail.

La vraie question est de savoir quel est le meilleur moyen de maintenir l’état. Dans notre cas, en ce qui concerne l'utilisateur actuellement connecté, nous stockons cet objet dans Session, car nous y faisons constamment référence pour son nom, son adresse électronique, son autorisation, etc.

Autres petites choses qui ne nécessitent aucune persistance à long terme, nous utilisons une combinaison de cookies et d'état de visualisation.

Lorsque vous souhaitez stocker des informations accessibles globalement dans votre application Web, vous pouvez utiliser l'attribut ThreadStatic . Cela transforme un membre static d'une Classe en un membre partagé par le thread actuel, mais pas par d'autres threads. L’avantage de ThreadStatic est qu’il n’est pas nécessaire de disposer d’un contexte Web. Par exemple, si votre back-end ne fait pas référence à System.Web , mais souhaite partager des informations là aussi, vous pouvez définir le id de l'utilisateur au début de toutes les requêtes de la propriété ThreadStatic et référencez-la dans votre dépendance sans avoir besoin d'accéder à l'objet Session .

Comme il s'agit de static mais uniquement d'un seul thread, nous nous assurons que les autres visiteurs simultanés ne reçoivent pas notre session. Cela fonctionne tant que vous vous assurez que la propriété est réinitialisée pour chaque demande. Cela en fait un compagnon idéal des cookies.

Je pense que l’utilisation de l’objet Session est acceptable dans ce cas, mais vous devez vous rappeler que la session peut expirer s’il n’ya pas d’activité du navigateur pendant une longue période ( HttpSessionState.Timeout détermine en combien de minutes le fournisseur d'état de session termine la session), il est donc préférable de vérifier la valeur. existence avant le retour:

public static Account GetCurrentAccount(HttpSessionState session)
{
    if (Session[ACCOUNT]!=null)
        return (Account)Session[ACCOUNT];
    else
        throw new Exception("Can't get current account. Session expired.");
}

Les informations à court terme, qui n'ont besoin que de vivre jusqu'à la demande suivante, peuvent également être stockées dans le ViewState . Cela signifie que les objets sont sérialisés et stockés dans la page envoyée au navigateur, qui est ensuite renvoyée au serveur lors d'un événement de clic ou similaire. Ensuite, le ViewState est décodé et transformé en objets, prêt à être récupéré.

Les sessions ne sont pas diaboliques, elles remplissent une fonction importante dans l'application ASP.NET, car elles servent des données devant être partagées entre plusieurs pages au cours de la "session" d'un utilisateur. Il y a quelques suggestions, je dirais d'utiliser la gestion de session SQL chaque fois que possible et de vous assurer que les objets que vous utilisez dans votre collection de sessions sont "sérialisables". La meilleure pratique consiste à utiliser l'objet de session lorsque vous avez absolument besoin de partager des informations d'état sur plusieurs pages et de ne pas l'utiliser quand vous n'en avez pas besoin. Les informations ne seront pas disponibles côté client. Une clé de session est conservée soit dans un cookie, soit via la chaîne de requête, soit à l'aide d'autres méthodes, en fonction de la configuration, puis les objets de session sont disponibles dans la table de la base de données ( Sauf si vous utilisez InProc, dans ce cas, vos sessions risquent d’être détruites lors du rechargement du site ou deviendront presque inutiles dans la plupart des environnements en cluster).

Je pense que le "mal" vient de trop utiliser la session. Si vous collez simplement tout ce qui y est (comme l’utilisation de variables globales pour tout), vous obtiendrez des performances médiocres et un simple gâchis.

Tout ce que vous mettez dans l'objet de session y reste pendant toute la durée de la session, à moins qu'il ne soit nettoyé. Une mauvaise gestion de la mémoire stockée à l'aide d'inproc et Stateserver vous obligera à faire évoluer votre système plus tôt que nécessaire. Stockez uniquement un ID pour la session / l'utilisateur dans la session et chargez ce qui est nécessaire dans l'objet cache à la demande à l'aide d'une classe d'assistance. De cette façon, vous pourrez ajuster sa durée de vie en fonction de la fréquence à laquelle nous avons utilisé les données. La prochaine version de asp.net pourrait avoir un cache distribué (rumeur).

Session as evil: Pas dans ASP.NET, correctement configuré. Oui, c'est idéal pour être aussi apatride que possible, mais la réalité est que vous ne pouvez pas vous y rendre d'ici. Cependant, vous pouvez faire en sorte que Session se comporte de manière à réduire son impact, notamment les sessions StateServer ou les bases de données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top