Comment accéder aux variables de session à partir de n'importe quelle classe dans ASP.NET?

157

J'ai créé un fichier de classe dans le dossier App_Code de mon application. J'ai une variable de session

Session["loginId"]

Je veux accéder à ces variables de session dans ma classe, mais lorsque j'écris la ligne suivante, cela donne une erreur

Session["loginId"]

Quelqu'un peut-il me dire comment accéder aux variables de session dans une classe créée dans le dossier app_code dans ASP.NET 2.0 (C #)

Prashant
la source

Réponses:

363

(Mis à jour pour être complet)
Vous pouvez accéder aux variables de session depuis n'importe quelle page ou contrôle en utilisant Session["loginId"]et depuis n'importe quelle classe (par exemple depuis l'intérieur d'une bibliothèque de classes), en utilisantSystem.Web.HttpContext.Current.Session["loginId"].

Mais s'il vous plaît lisez la suite pour ma réponse originale ...


J'utilise toujours une classe wrapper autour de la session ASP.NET pour simplifier l'accès aux variables de session:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

Cette classe stocke une instance d'elle-même dans la session ASP.NET et vous permet d'accéder à vos propriétés de session de manière sécurisée à partir de n'importe quelle classe, par exemple comme ceci:

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

Cette approche a de nombreux avantages:

  • cela vous évite beaucoup de casting
  • vous n'avez pas à utiliser des clés de session codées en dur dans toute votre application (par exemple Session ["loginId"]
  • vous pouvez documenter vos éléments de session en ajoutant des commentaires de doc XML sur les propriétés de MySession
  • vous pouvez initialiser vos variables de session avec des valeurs par défaut (par exemple en vous assurant qu'elles ne sont pas nulles)
M4N
la source
6
Il n'est pas nécessaire d'écrire de code, utilisez comme indiqué dans la réponse. Par exemple, "public int LoginId {get; set;}" -> cela s'appelle une propriété automatique.
M4N
4
Si vous utilisez .net 3.x, vous pouvez utiliser les propriétés automatiques comme indiqué dans mon code. Avec .net 2.x / 1.x, ce n'est pas disponible et vous devez implémenter vous-même le getter / setter de vos propriétés: private int _loginId; public int LoginId {get {return _loginId; } set {_loginId = valeur; }}
M4N
2
Ça a l'air cool maintenant, je pense que j'ai eu la réponse à mon problème, et je suis déjà en train d'utiliser votre chemin, c'est très propre et facile de maintenir toutes mes variables de session en un seul endroit. Merci @Martin, vous êtes génial.
Prashant
23
@ M4N, j'aimerais pouvoir exprimer un peu plus de gratitude qu'un +1. C'est devenu ma façon préférée de gérer la session / le cache dans mes projets. Mon code, littéralement, vous remercie.
Brandon Boone
4
@Kristopher alors que la propriété 'Current' est statique, l'instance de MySession retournée n'est pas ... donc ça va. Les méthodes et propriétés statiques peuvent être utilisées en toute sécurité de cette manière.
Darren
104

Accédez à la session via les threads HttpContext: -

HttpContext.Current.Session["loginId"]
AnthonyWJones
la source
Merci beaucoup Anthony pour cette étape simple.
Kings
Merci beaucoup Anthony, + 1 pour ça
Owais Qureshi
Merci. J'ai oublié ce qu'était l'espace de noms :)
Anthony Horne
@AnthonyWJones j'ai utilisé votre méthode, mais j'ai un problème, pouvez-vous m'expliquer, où je me trompe ou quelle est la bonne façon d'utiliser, ma question stackoverflow.com/questions/45254279/…
adnan
et si vous souhaitez convertir en HttpSessionStateBase: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/…
sobelito
24

Le problème avec la solution suggérée est qu'elle peut interrompre certaines fonctionnalités de performances intégrées à SessionState si vous utilisez un stockage de session hors processus. (soit «Mode serveur d'état» ou «Mode serveur SQL»). En mode oop, les données de session doivent être sérialisées à la fin de la demande de page et désérialisées au début de la demande de page, ce qui peut être coûteux. Pour améliorer les performances, SessionState tente de désérialiser uniquement ce qui est nécessaire en désérialisant uniquement la variable lors de son premier accès, et il ne re-sérialise et remplace que la variable qui a été modifiée. Si vous avez beaucoup de variables de session et que vous les mettez toutes dans une classe, pratiquement tout dans votre session sera désérialisé sur chaque requête de page qui utilise session et tout devra être sérialisé à nouveau même si une seule propriété a été modifiée en raison de la modification de la classe. Juste quelque chose à considérer si vous utilisez beaucoup de session et un mode oop.

Ernie
la source
4
+1 pour avoir apporté cela. Si vous n'utilisez pas InProc for Session, Ernie est correct à 100%. InProc est de toute façon très limité, car il ne prend pas en charge les webfarms et sera perdu si l'application redémarre. Notez que par coût de performance, nous recherchons une prime de 20% dans l'utilisation du mode State Server, et des coûts de sérialisation sont ajoutés en plus de cela. Comme vous pouvez l'imaginer, cela peut coûter cher. Vous pouvez éviter une partie de la surcharge de sérialisation en vous en tenant aux types primitifs (par exemple int, string, char, byte, etc.). Les objets personnalisés seront confrontés à la sérialisation. Méfiez-vous de l'utilisateur.
Zack Jannsen
+1 Bon point. Un changement qui marierait les deux concepts serait que chaque propriété de cette classe "session" personnalisée appelle la session asp.net elle-même au lieu d'un gros objet en session. Vous devez faire le casting de type que l'approche de @ M4N évite, mais cela en vaut peut-être la peine si vous ne lisez qu'une partie de la session à chaque fois.
eol
12

Les réponses présentées avant la mienne fournissent des solutions appropriées au problème, cependant, je pense qu'il est important de comprendre pourquoi cette erreur se produit:

La Sessionpropriété de Pagerenvoie une instance de type HttpSessionStaterelative à cette requête particulière. Page.Sessionéquivaut en fait à appeler Page.Context.Session.

MSDN explique comment cela est possible:

Étant donné que les pages ASP.NET contiennent une référence par défaut à l'espace de noms System.Web (qui contient la HttpContextclasse), vous pouvez référencer les membres de HttpContextsur une page .aspx sans la référence de classe pleinement qualifiée à HttpContext.

Toutefois, lorsque vous essayez d'accéder à cette propriété dans une classe dans App_Code, la propriété ne vous sera pas disponible à moins que votre classe ne dérive de la classe de page.

Ma solution à ce scénario souvent rencontré est que je ne transmets jamais d'objets de page aux classes . Je préférerais extraire les objets requis de la page Session et les transmettre à la Classe sous la forme d'une collection nom-valeur / Array / List, selon le cas.

Cerebrus
la source
C'est une excellente explication, cela m'a aidé à +1 pour ça :)
Owais Qureshi
1

J'ai eu la même erreur, car j'essayais de manipuler des variables de session dans une classe Session personnalisée.

J'ai dû passer le contexte actuel (system.web.httpcontext.current) dans la classe, puis tout s'est bien passé.

MA

MunsterMan
la source
1

Dans le noyau asp.net, cela fonctionne différemment:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Source: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/

Matty
la source
0

Cela devrait être plus efficace tant pour l'application que pour le développeur.

Ajoutez la classe suivante à votre projet Web:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

Voici la mise en œuvre:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Capitaine Amérique
la source