Come accedere alle variabili di sessione da qualsiasi classe in ASP.NET?


157

Ho creato un file di classe nella cartella App_Code nella mia applicazione. Ho una variabile di sessione

Session["loginId"]

Voglio accedere a queste variabili di sessione nella mia classe, ma quando scrivo la riga seguente, viene visualizzato un errore

Session["loginId"]

Qualcuno può dirmi come accedere alle variabili di sessione all'interno di una classe creata nella cartella app_code in ASP.NET 2.0 (C #)

Risposte:


363

(Aggiornato per completezza)
È possibile accedere alle variabili di sessione da qualsiasi pagina o controllo utilizzando Session["loginId"]e da qualsiasi classe (ad esempio dall'interno di una libreria di classi), utilizzandoSystem.Web.HttpContext.Current.Session["loginId"].

Ma per favore continua a leggere per la mia risposta originale ...


Uso sempre una classe wrapper attorno alla sessione ASP.NET per semplificare l'accesso alle variabili di sessione:

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

Questa classe memorizza un'istanza di se stessa nella sessione ASP.NET e consente di accedere alle proprietà della sessione in modo sicuro da qualsiasi classe, ad esempio in questo modo:

int loginId = MySession.Current.LoginId;

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

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

Questo approccio ha diversi vantaggi:

  • ti salva da un sacco di tipi-casting
  • non è necessario utilizzare chiavi di sessione codificate in tutta l'applicazione (ad es. Session ["loginId"]
  • puoi documentare gli elementi della sessione aggiungendo commenti doc XML sulle proprietà di MySession
  • puoi inizializzare le variabili di sessione con valori predefiniti (ad esempio assicurandoti che non siano nulli)

6
Non è necessario scrivere alcun codice, utilizzare come mostrato nella risposta. Ad esempio "public int LoginId {get; set;}" -> questa si chiama proprietà automatica.
M4N,

4
Se stai usando .net 3.x puoi usare le proprietà automatiche come mostrato nel mio codice. Con .net 2.x / 1.x questo non è disponibile e devi implementare tu stesso il getter / setter delle tue proprietà: private int _loginId; public int LoginId {get {return _loginId; } set {_loginId = value; }}
M4N,

2
Sembra fantastico ora, penso di aver ottenuto la risposta al mio problema, e sto sempre usando la tua strada, è molto pulito e facile da mantenere tutte le mie variabili di sessione in un unico posto. Grazie @Martin, sei FANTASTICO.
Prashant,

23
@ M4N, vorrei poter esprimere un po 'più di gratitudine di un +1. Questo è diventato il mio modo preferito di gestire la sessione / cache nei miei progetti. Il mio codice, letteralmente, ti sta ringraziando.
Brandon Boone,

4
@Kristopher mentre la proprietà 'Current' è statica l'istanza di MySession restituita non lo è ... quindi va bene. I metodi e le proprietà statici sono sicuri da usare in questo modo.
Darren,

104

Accedi alla sessione tramite i thread HttpContext: -

HttpContext.Current.Session["loginId"]

Grazie mille Anthony per questo semplice passaggio.
Re

Grazie mille Anthony, + 1 per questo
Owais Qureshi

Grazie. Dimenticato quale fosse lo spazio dei nomi :)
Anthony Horne,

@AnthonyWJones ho usato il tuo metodo, ma ho un problema, puoi spiegarmi dove ho sbagliato o qual è il modo corretto di utilizzare, la mia domanda stackoverflow.com/questions/45254279/…
adnan,

e se si desidera convertire in HttpSessionStateBase: sessione HttpSessionStateBase = nuovo HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/...
sobelito

24

Il problema con la soluzione suggerita è che può interrompere alcune funzionalità prestazionali integrate in SessionState se si utilizza un archivio sessioni fuori processo. ("Modalità server di stato" o "Modalità server SQL"). Nelle modalità oop i dati della sessione devono essere serializzati alla fine della richiesta di pagina e deserializzati all'inizio della richiesta di pagina, il che può essere costoso. Per migliorare le prestazioni, SessionState tenta di deserializzare solo ciò che è necessario solo deserializzando la variabile quando si accede per la prima volta e re-serializza e sostituisce solo la variabile che è stata modificata. Se hai molte variabili di sessione e le inserisci tutte in una classe, essenzialmente tutto nella tua sessione verrà deserializzato su ogni richiesta di pagina che utilizza la sessione e tutto dovrà essere nuovamente serializzato anche se solo 1 proprietà modificata perché la classe è cambiata. Solo qualcosa da considerare se stai usando molte sessioni e una modalità oop.


4
+1 per aumentare questo valore. Se non si utilizza InProc per Session, Ernie è corretto al 100%. InProc è comunque molto limitato, in quanto non supporta webfarm e andrà perso se l'applicazione si riavvia. Si noti che, in base al costo delle prestazioni, stiamo osservando un premio del 20% nell'uso della modalità Server statale, oltre a costi di serializzazione. Come puoi immaginare, questo può diventare costoso. È possibile evitare alcune delle spese generali di serializzazione attenendosi ai tipi primitivi (ad esempio int, string, char, byte, ecc.). Gli oggetti personalizzati dovranno affrontare la serializzazione. Attenzione all'utente.
Zack Jannsen,

+1 buon punto. Una modifica che sposerebbe i due concetti sarebbe quella di avere ciascuna proprietà su questa classe "session" personalizzata che chiama la sessione asp.net stessa invece di un grande oggetto nella sessione. Devi fare il cast di tipo che l'approccio di @ M4N evita, ma forse ne vale la pena se leggi solo alcune sessioni ogni volta.
eol

12

Le risposte presentate prima delle mie forniscono soluzioni adeguate al problema, tuttavia, ritengo sia importante capire perché questo errore risulta:

La Sessionproprietà di Pagerestituisce un'istanza di tipo HttpSessionStaterelativa a quella particolare richiesta. Page.Sessionè in realtà equivalente a chiamare Page.Context.Session.

MSDN spiega come ciò sia possibile:

Poiché le pagine ASP.NET contengono un riferimento predefinito allo spazio dei nomi System.Web (che contiene la HttpContextclasse), è possibile fare riferimento ai membri di HttpContextuna pagina aspx senza il riferimento completo alla classe HttpContext.

Tuttavia, quando si tenta di accedere a questa proprietà all'interno di una classe in App_Code, la proprietà non sarà disponibile a meno che la classe non derivi dalla classe Page.

La mia soluzione a questo scenario spesso riscontrato è che non passo mai oggetti di pagina alle classi . Preferirei estrarre gli oggetti richiesti dalla pagina Sessione e passarli alla Classe sotto forma di una raccolta nome-valore / Matrice / Elenco, a seconda del caso.


Questa è un'ottima spiegazione, mi ha aiutato +1 per questo :)
Owais Qureshi il

1

Ho avuto lo stesso errore, perché stavo cercando di manipolare le variabili di sessione all'interno di una classe Session personalizzata.

Ho dovuto passare il contesto corrente (system.web.httpcontext.current) nella classe, e poi tutto ha funzionato bene.

MA


1

Nel core asp.net funziona diversamente:

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

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


0

Questo dovrebbe essere più efficiente sia per l'applicazione che per lo sviluppatore.

Aggiungi la seguente classe al tuo progetto 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);
    }
}

}

Ecco l'implementazione:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.