Jak uzyskać dostęp do zmiennych sesji z dowolnej klasy w ASP.NET?


157

Utworzyłem plik klasy w folderze App_Code w mojej aplikacji. Mam zmienną sesji

Session["loginId"]

Chcę uzyskać dostęp do tych zmiennych sesji w mojej klasie, ale kiedy piszę następujący wiersz, pojawia się błąd

Session["loginId"]

Czy ktoś może mi powiedzieć, jak uzyskać dostęp do zmiennych sesji w ramach klasy utworzonej w folderze app_code w ASP.NET 2.0 (C #)

Odpowiedzi:


363

(Zaktualizowano dla kompletności)
Możesz uzyskać dostęp do zmiennych sesji z dowolnej strony lub sterować za pomocą Session["loginId"]iz dowolnej klasy (np. Z wnętrza biblioteki klas), używającSystem.Web.HttpContext.Current.Session["loginId"].

Ale proszę przeczytaj moją pierwotną odpowiedź ...


Zawsze używam klasy opakowania wokół sesji ASP.NET, aby uprościć dostęp do zmiennych sesji:

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; }
}

Ta klasa przechowuje jedno samo wystąpienie w sesji ASP.NET i umożliwia dostęp do właściwości sesji w sposób bezpieczny dla typu z dowolnej klasy, np. Tak:

int loginId = MySession.Current.LoginId;

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

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

Takie podejście ma kilka zalet:

  • oszczędza ci to wielu rzutów czcionek
  • nie musisz używać zakodowanych na stałe kluczy sesji w całej aplikacji (np. Session ["loginId"]
  • możesz udokumentować swoje pozycje sesji, dodając komentarze do dokumentów XML we właściwościach MySession
  • możesz zainicjować zmienne sesji z wartościami domyślnymi (np. zapewniając, że nie są zerowe)

6
Nie ma potrzeby pisania żadnego kodu, użyj jak pokazano w odpowiedzi. Np. "Public int LoginId {get; set;}" -> nazywa się to właściwością automatyczną.
M4N

4
Jeśli używasz .net 3.x, możesz użyć właściwości automatycznych, jak pokazano w moim kodzie. W przypadku .net 2.x / 1.x nie jest to dostępne i musisz samodzielnie zaimplementować metodę pobierającą / ustawiającą właściwości: private int _loginId; public int LoginId {get {return _loginId; } ustaw {_loginId = wartość; }}
M4N

2
Wygląda teraz fajnie, myślę, że znalazłem odpowiedź na mój problem i już używam twojego sposobu, jest bardzo czysty i łatwy do utrzymania wszystkich moich zmiennych sesji w jednym miejscu. Dzięki @Martin, jesteś NIESAMOWITY.
Prashant

23
@ M4N, Chciałbym móc wyrazić trochę więcej wdzięczności niż +1. Stało się to moim ulubionym sposobem radzenia sobie z sesją / pamięcią podręczną w moich projektach. Mój kod dosłownie ci dziękuje.
Brandon Boone

4
@Kristopher podczas gdy właściwość „Current” jest statyczna, zwrócona instancja MySession nie jest ... więc jest w porządku. W ten sposób można bezpiecznie używać metod i właściwości statycznych .
Darren

104

Uzyskaj dostęp do sesji za pośrednictwem wątków HttpContext: -

HttpContext.Current.Session["loginId"]

Wielkie dzięki Anthony za ten prosty krok.
Kings

Wielkie dzięki Anthony, +1 za to
Owais Qureshi

Dzięki. Zapomniałem, jaka była przestrzeń nazw :)
Anthony Horne

@AnthonyWJones Użyłem twojej metody, ale mam problem, czy możesz mi wyjaśnić, gdzie się mylę lub jaki jest właściwy sposób, moje pytanie stackoverflow.com/questions/45254279/ ...
adnan

a jeśli chcesz przekonwertować na HttpSessionStateBase: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/…
sobelito

24

Problem z sugerowanym rozwiązaniem polega na tym, że może ono zepsuć niektóre funkcje wydajności wbudowane w SessionState, jeśli używasz pamięci sesji poza procesem. („Tryb serwera stanu” lub „Tryb serwera SQL”). W trybach oop dane sesji muszą być serializowane na końcu żądania strony i deserializowane na początku żądania strony, co może być kosztowne. Aby poprawić wydajność, SessionState próbuje deserializować tylko to, co jest potrzebne tylko przez deserializację zmiennej, gdy jest dostępna po raz pierwszy, i tylko ponownie serializuje i zastępuje zmienną, która została zmieniona. Jeśli masz dużo zmiennych sesji i wepchniesz je wszystkie do jednej klasy, zasadniczo wszystko w sesji zostanie zdeserializowane na każdym żądaniu strony, które używa sesji, i wszystko będzie musiało zostać ponownie serializowane, nawet jeśli tylko 1 właściwość zostanie zmieniona, ponieważ klasa uległa zmianie. Po prostu coś do rozważenia, jeśli używasz dużo sesji i trybu oop.


4
+1 za podniesienie tego. Jeśli nie używasz InProc do sesji, to Ernie jest w 100% poprawny. InProc i tak jest bardzo ograniczony, ponieważ nie obsługuje farm internetowych i zostanie utracony, jeśli aplikacja zostanie ponownie uruchomiona. Uwaga: ze względu na koszt wydajności patrzymy na 20% premię w korzystaniu z trybu serwera stanu, a do tego dodawane są koszty serializacji. Jak możesz sobie wyobrazić, może to być kosztowne. Możesz uniknąć niektórych narzutów serializacji, trzymając się typów pierwotnych (np. Int, string, char, byte itp.). Obiekty niestandardowe zostaną poddane serializacji. Uwaga użytkownika.
Zack Jannsen

+1 Słuszna uwaga. Zmiana, która połączyłaby te dwie koncepcje, polegałaby na tym, że każda właściwość tej niestandardowej klasy „sesji” wywoływałaby samą sesję asp.net zamiast jednego dużego obiektu w sesji. Muszę wykonać rzutowanie typów, którego unika podejście @ M4N, ale może warto, jeśli za każdym razem czytasz tylko część sesji.
eol

12

Przedstawione wcześniej odpowiedzi dostarczają trafnych rozwiązań problemu, jednak uważam, że ważne jest, aby zrozumieć, dlaczego ten błąd występuje:

SessionNieruchomość z Pagezwraca instancję typu HttpSessionStatew stosunku do danego wniosku. Page.Sessionjest właściwie równoznaczne z dzwonieniem Page.Context.Session.

MSDN wyjaśnia, jak to jest możliwe:

Ponieważ strony ASP.NET zawierają domyślne odwołanie do przestrzeni nazw System.Web (która zawiera HttpContextklasę), można odwoływać się do elementów członkowskich HttpContextna stronie .aspx bez w pełni kwalifikowanego odwołania do klasy HttpContext.

Jednak podczas próby uzyskania dostępu do tej właściwości w klasie w App_Code właściwość nie będzie dostępna, chyba że Twoja klasa pochodzi z klasy strony.

Moim rozwiązaniem tego często spotykanego scenariusza jest to, że nigdy nie przekazuję obiektów strony do klas . Wolałbym raczej wyodrębnić wymagane obiekty ze strony Session i przekazać je do Class w postaci kolekcji nazwa-wartość / Array / List, w zależności od przypadku.


To świetne wyjaśnienie, pomogło mi to dać +1 :)
Owais Qureshi,

1

Miałem ten sam błąd, ponieważ próbowałem manipulować zmiennymi sesji wewnątrz niestandardowej klasy sesji.

Musiałem przekazać aktualny kontekst (system.web.httpcontext.current) do klasy, a potem wszystko poszło dobrze.

MAMA


1

W asp.net core działa to inaczej:

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");
    }
}

Źródło: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/


0

Powinno to być bardziej wydajne zarówno dla aplikacji, jak i dla programisty.

Dodaj następującą klasę do swojego projektu internetowego:

/// <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);
    }
}

}

Oto realizacja:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.