Comment utiliser des sessions dans une application ASP.NET MVC 4?

113

Je suis nouveau sur ASP.NET MVC. J'ai déjà utilisé PHP et il était facile de créer une session et de sélectionner des enregistrements d'utilisateurs en fonction des variables de session actuelles.

J'ai cherché partout sur Internet un didacticiel simple étape par étape qui peut me montrer comment créer et utiliser des sessions dans mon application C # ASP.NET MVC 4. Je souhaite créer une session avec des variables utilisateur auxquelles je peux accéder de n'importe où dans mes contrôleurs et pouvoir utiliser les variables dans mes requêtes LINQ.

Thuto Paul Gaotingwe
la source
2
duplication possible de Comment maintenir la session utilisateur avec ASP.NET MVC
adatapost
2
Cet article pourrait vous intéresser: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel Hollinrake

Réponses:

160

Essayer

//adding data to session
//assuming the method below will return list of Products

var products=Db.GetProducts();

//Store the products to a session

Session["products"]=products;

//To get what you have stored to a session

var products=Session["products"] as List<Product>;

//to clear the session value

Session["products"]=null;
Jobert Enamno
la source
3
Merci Jobert! tu m'as donné une idée! vous vous demandez simplement ..., il est possible d'ajouter des variables utilisateur à une session lors de la connexion? et aurai-je également accès aux variables de session (créées une seule fois) sur différents contrôleurs de mon application?
Thuto Paul Gaotingwe
31
Vous pouvez stocker n'importe quoi ou n'importe quelle donnée de n'importe quel type dans une session. Une fois créé, vous pouvez accéder à la valeur qui y est stockée dans toutes les vues et contrôleurs. Notez également que la session créée n'est accessible que par utilisateur et par navigateur. Cela signifie que la session créée par User1 à l'aide de Firefox n'est pas accessible par le même utilisateur à l'aide d'IE. Il y a aussi des choses que vous ne devriez pas faire avec une session comme. NE stockez PAS de grandes données dessus. Cela peut ralentir les performances de votre serveur. Enfin, ne stockez PAS de données sensibles sur une session telles que le mot de passe ou le numéro de carte de crédit
Jobert Enamno
2
Merci encore une fois! Où puis-je le créer pour pouvoir y accéder via différents contrôleurs?
Thuto Paul Gaotingwe
2
@JobertEnamno est-il sûr de stocker la valeur qui provient de WebSecurity.CurrentUserIdsorte qu'elle ne la tire pas de la base de données plusieurs fois (j'ai trouvé que c'était très coûteux)?
Andrius Naruševičius
2
Il n'y a pas de session entre contrôleurs, donc lorsque vous demandez un autre contrôleur, par exemple de Account/LogOnà Home/Index, Session["FirstName"]c'est null. Les développeurs doivent créer un contrôleur parent ( BaseController) et définir un champ protégé ( internal protected HttpSessionStateBase SharedSession) qui peut exposer la variable Session partagée dans tous les sous-contrôleurs (cela suppose que tous vos contrôleurs d'application héritent du BaseController)
Bellash
63

En raison de la nature sans état du Web, les sessions sont également un moyen extrêmement utile de persister des objets à travers les demandes en les sérialisant et en les stockant dans une session.

Un cas d'utilisation parfait de ceci pourrait être si vous avez besoin d'accéder à des informations régulières dans toute votre application, pour enregistrer des appels de base de données supplémentaires à chaque demande, ces données peuvent être stockées dans un objet et non sérialisées à chaque demande, comme ceci:

Notre objet réutilisable et sérialisable:

[Serializable]
public class UserProfileSessionData
{
    public int UserId { get; set; }

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Cas d'utilisation:

public class LoginController : Controller {

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var profileData = new UserProfileSessionData {
                UserId = model.UserId,
                EmailAddress = model.EmailAddress,
                FullName = model.FullName
            }

            this.Session["UserProfile"] = profileData;
        }
    }

    public ActionResult LoggedInStatusMessage()
    {
        var profileData = this.Session["UserProfile"] as UserProfileSessionData;

        /* From here you could output profileData.FullName to a view and
        save yourself unnecessary database calls */
    }

}

Une fois cet objet sérialisé, nous pouvons l'utiliser sur tous les contrôleurs sans avoir besoin de le créer ou d'interroger à nouveau la base de données pour les données qu'il contient.

Injectez votre objet de session à l'aide de l'injection de dépendances

Dans un monde idéal, vous `` programmez sur une interface, pas une implémentation '' et injectez votre objet de session sérialisable dans votre contrôleur en utilisant votre conteneur Inversion of Control de votre choix, comme ceci (cet exemple utilise StructureMap car c'est celui avec lequel je suis le plus familier ).

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
    }

    public static IUserProfileSessionData GetUserProfileFromSession()
    {
        var session = HttpContext.Current.Session;
        if (session["UserProfile"] != null)
        {
            return session["UserProfile"] as IUserProfileSessionData;
        }

        /* Create new empty session object */
        session["UserProfile"] = new UserProfileSessionData();

        return session["UserProfile"] as IUserProfileSessionData;
    }
}

Vous enregistrerez alors ceci dans votre Global.asax.csdossier.

Pour ceux qui ne sont pas familiarisés avec l'injection d'objets de session, vous pouvez trouver un article de blog plus détaillé sur le sujet ici .

Un mot d'avertissement:

Il convient de noter que les sessions doivent être réduites au minimum, de grandes sessions peuvent commencer à causer des problèmes de performances.

Il est également recommandé de ne pas y stocker de données sensibles (mots de passe, etc.).

Joseph Woodward
la source
Où mettriez-vous la définition de classe? Je suis encore assez nouveau dans tout, mais je suis juste curieux de savoir comment les autres contrôleurs verront la classe et sauront ce que c'est. L'ajoutez-vous simplement en haut du contrôleur? Je pensais à SessionStart dans global.asax que j'initialiserais les choses mais ce n'est peut-être pas la meilleure façon de le faire.
Shaun314
@ Shaun314 Idéalement, vous utiliseriez un conteneur IoC pour injecter l'objet dans votre contrôleur via l'injection de dépendances (voir edit).
Joseph Woodward
1
Je stocke des informations de session après la connexion de l'utilisateur à l'aide d'Identity 2. Je ne peux pas récupérer ces informations dans d'autres actions et contrôleurs que la première action vers laquelle je redirige l'utilisateur. Une idée?
Akbari
17

Voici comment l'état de session fonctionne dans ASP.NET et ASP.NET MVC:

Vue d'ensemble de l'état de session ASP.NET

En gros, vous faites ceci pour stocker une valeur dans l'objet Session:

Session["FirstName"] = FirstNameTextBox.Text;

Pour récupérer la valeur:

var firstName = Session["FirstName"];
Leniel Maccaferri
la source
10
Il n'y a pas de session entre contrôleurs, donc lorsque vous demandez un autre contrôleur, par exemple de Accountà Home, Session ["FirstName"] est nulle. Les développeurs doivent créer BaseControlleret définir un champ protégé ( internal protected HttpSessionStateBase SharedSession) qui peut exposer la Sessionvariable partagée dans tous les sous-contrôleurs (cela suppose que tous vos contrôleurs d'application héritent du BaseController)
Bellash
4
Umm, bien sûr? Il y a une variable de session dans Controller (le contrôleur de base fourni par MVC).
aeliusd
7
@Bellash c'est complètement faux. Les sessions sont disponibles sur tous les contrôleurs. Je viens de définir Session ["test"] dans HomeController puis de la lire dans mon AccountController.
niico
0

Vous pouvez stocker tout type de données dans une session en utilisant:

Session["VariableName"]=value;

Cette variable durera environ 20 minutes.

Ulysse
la source
-8

U peut stocker n'importe quelle valeur dans la session comme Session ["FirstName"] = FirstNameTextBox.Text; mais je suggérerai que vous preniez comme champ statique dans le modèle, attribuez-lui une valeur et vous pourrez accéder à cette valeur de champ n'importe où dans l'application. Vous n'avez pas besoin de session. la session doit être évitée.

public class Employee
{
   public int UserId { get; set; }
   public string EmailAddress { get; set; }
   public static string FullName { get; set; }
}

sur le contrôleur - Employee.FullName = "ABC"; Maintenant, vous pouvez accéder à ce nom complet n'importe où dans l'application.

Mukul Sharma
la source
10
Le stockage de données sur des champs statiques, en particulier des données utilisateur telles que le nom de l'employé, causera de graves problèmes dans les environnements multi-utilisateurs. Lorsque deux utilisateurs différents se sont connectés au système, ils verront le même Employee.EmailAddress puisque le champ statique sur Employee est le même pour chaque instance.
Gökçer Gökdal