1
votes

Existe-t-il un moyen d'utiliser la session pour les objets dans asp.net core comme dans les formulaires Web?

J'ai un projet sous forme de formulaires Web et j'essaye de le convertir en noyau asp.net. Mon problème est que dans les formulaires Web, j'enregistre un objet dans la session et lorsque je l'obtiens, je peux y apporter des modifications et les conserver. D'un autre côté, dans le noyau, j'ai défini l'objet sur la session en le sérialisant. Lorsque je l'obtiens et que je fais des modifications, cela n'affecte pas l'objet stocké dans la session. Existe-t-il un moyen de sauvegarder l'objet tel quel (sans le sérialiser), donc lorsque je l'obtiens à partir de la session et que j'y apporte des modifications, pour continuer à l'utiliser et ne pas avoir à le définir à nouveau dans la session?

La session était

AppHttpContext.Current.Session.GetString("object") 

Et l'a fait

 System.Web.HttpContext.Current.Session["object"]

Et puis je l'ai désérialisée en l'objet que je veux.

Ps: J'ai utilisé AppHttpContext pour obtenir la session en dehors d'un contrôleur


1 commentaires

C'est un peu une question X / Y. Vous pouvez faire fonctionner les sessions, mais vous devriez essayer d'éviter cela. Le reste de votre problème n'est pas très clair, que signifie «sans sérialisation»?


4 Réponses :


0
votes

ASP.NET Core ne prend pas en charge l'enregistrement direct des objets dans Session comme le peuvent les projets Web Forms. Dans ASP.NET Cpre, il n'y a qu'une prise en charge directe de l'enregistrement des types primitifs dans Session comme une chaîne , int ou byte tableau. Ainsi, tout objet plus complexe devra être sérialisé dans une chaîne ou sérialisé directement dans un tableau d'octets, et cette sérialisation peut ensuite être stockée dans Session .

Il est courant que les gens accomplissent cela en effectuant une sérialisation JSON de l'objet pour générer une chaîne, puis en enregistrant la chaîne dans Session . Mais lorsque vous récupérez la chaîne JSON de Session et que vous la désérialisez en un objet, toute modification apportée à cet objet ne sera pas reflétée dans le JSON précédent qui représentait l'objet actuellement stocké dans la session. Ainsi, les modifications apportées à l'objet ne sont pas directement reflétées dans Session .

C'est un comportement très différent de ce qui a été vu dans Web Forms et résulte du fait que l'objet n'est pas stocké en session, c'est la sérialisation. Donc, si vous modifiez l'objet et souhaitez que ces modifications soient stockées dans la session, vous devrez sérialiser l'objet à nouveau et stocker cette sérialisation (par exemple, json) dans la session.

Cela vous aide-t-il?


2 commentaires

Oui, mais quelle est l'alternative pour accomplir le scénario ci-dessus?


Ce n'est pas une alternative si vous souhaitez utiliser les fonctionnalités de session fournies par ASP.NET Core. Je suppose que vous pourriez dire que l'alternative est d'écrire un support de session personnalisé. Je l'ai fait par exemple pour pouvoir stocker ma session dans Sql Server avec une prise en charge optimiste du verrouillage au niveau de la clé de session, mais je ne pense pas que la plupart des utilisateurs d'ASP.NET Core écrivent leur propre prise en charge de session personnalisée. :-)



3
votes

Techniquement, ASP.NET n'a jamais non plus pris en charge cela. C'était un hasard qui fonctionnait lors de l'utilisation de sessions InProc (c'est-à-dire en mémoire), en raison de la façon dont le stockage de session fonctionnait dans ce cas. Si vous utilisiez un autre magasin de sessions comme SQL Server, vous devrez également sérialiser / désérialiser les objets dans et hors de la session. ASP.NET Core diffère uniquement en ce qu'il utilise un magasin de session généralisé, donc il force tout objet à être sérialisé / désérialisé, même si vous utilisez un magasin en mémoire.

Cela dit, votre problème ici est que vous ne persistez tout simplement pas à rétablir vos modifications. Encore une fois, vous vous fiez à un comportement accidentel. Étant donné qu'ASP.NET persistait directement l'objet en mémoire, l'exécution d'opérations sur cet objet "persistait" automatiquement car il s'agissait de la même référence. Lors de la désérialisation, vous créez une nouvelle instance, les opérations ne persisteront donc pas à moins que vous ne sérialisiez à nouveau l'objet dans la session par la suite.

Enfin, Web Forms ou non, ce n'était jamais une manière recommandée ou même correcte de faire les choses. Le stockage de session est volatile. Il n'est destiné à rien d'autre que la persistance à court terme (et non fiable). En d'autres termes, vous ne pouvez jamais compter sur quelque chose dans la session, vous devez donc toujours coder de manière défensive autour du cas où les données n'existent pas. Si vous dépendez de quelque chose qui se trouve là-bas, comme cela semble être le cas ici, alors vous vous êtes toujours préparé à l'échec.

Cependant, si vous faites quelque chose comme un formulaire en plusieurs étapes, il est acceptable que les étapes individuelles entrent dans la session, bien que vous devriez en fait utiliser TempData plutôt que Session pour cela. À la dernière étape, cependant, votre objet composé doit être conservé dans quelque chose comme SQL Server, pas dans la session. Dans pratiquement tous les autres cas, vous devez simplement persister dans quelque chose comme SQL Server et éviter complètement Session .


0 commentaires

0
votes

La tâche de migration ne sera pas simple.

Vous pouvez suivre ces étapes:

1) Remplacez d'abord votre dépendance à Session sur un type de service que vous pouvez injecter dans des contrôleurs ou d'autres services. Une bonne idée serait de coder en dur les valeurs de ce service pour vérifier si tout le code dépendant de votre implémentation de session précédente est capable d'utiliser le nouveau service.

2) Implémentez un filtre (par exemple en implémentant IAsyncPageFilter dans le cas de pages Razor) pour accéder à l'utilisateur HttpContext et configurer une sorte d'objet de recherche qui peut être récupéré à partir d'une implémentation de cache - Une bonne idée serait d'utiliser un Cache distribué Redis. Cet objet doit avoir la clé comme identité d'utilisateur - les valeurs peuvent être les données que vous souhaitez ajouter à une "session". Utilisez un service «Cache» pour implémenter cela, en masquant les détails d'implémentation du Cache du code client. (N'oubliez pas de créer ces dépendances de portée "Request" afin que l'utilisateur HttpContext soit correctement rempli.)

3) Implémentez des méthodes sur un nouveau service pour ajouter / modifier l'objet Cache pour garder vos données de "session" à jour.

Morale de l'histoire: réduisez la dépendance vis-à-vis des fonctionnalités spécifiques de la plate-forme. Au moins encapsulez ces dépendances en utilisant un type de service qui peut être remplacé ultérieurement sans code client en fonction de ces fonctionnalités.


0 commentaires

3
votes

Pour utiliser un objet / tableau en session, vous avez besoin de quelques personnalisations: `

var objComplex = HttpContext.Session.GetObject("ComplexObject");

Vous pouvez maintenant le définir de cette façon:

var objComplex = new ComplexClass();
HttpContext.Session.SetObject("ComplexObject", objNew);

Et récupérez-le:

public static class SessionExtensions {
public static void SetObject(this ISession session, string key, object value)
{
    session.SetString(key, JsonConvert.SerializeObject(value));
}

public static T GetObject<T>(this ISession session, string key)
{
    var value = session.GetString(key);
    return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
} }


0 commentaires