Wie kann ich von einer beliebigen Klasse in ASP.NET auf Sitzungsvariablen zugreifen?

157

Ich habe in meiner Anwendung eine Klassendatei im Ordner App_Code erstellt. Ich habe eine Sitzungsvariable

Session["loginId"]

Ich möchte auf diese Sitzungsvariablen in meiner Klasse zugreifen, aber wenn ich die folgende Zeile schreibe, wird ein Fehler ausgegeben

Session["loginId"]

Kann mir jemand sagen, wie ich auf Sitzungsvariablen innerhalb einer Klasse zugreifen kann, die im Ordner app_code in ASP.NET 2.0 (C #) erstellt wurde?

Prashant
quelle

Antworten:

363

(Der Vollständigkeit halber aktualisiert)
Sie können von jeder Seite oder jedem Steuerelement mit Session["loginId"]und von jeder Klasse (z. B. aus einer Klassenbibliothek) mit auf Sitzungsvariablen zugreifenSystem.Web.HttpContext.Current.Session["loginId"].

Aber bitte lesen Sie weiter für meine ursprüngliche Antwort ...


Ich verwende immer eine Wrapper-Klasse um die ASP.NET-Sitzung, um den Zugriff auf Sitzungsvariablen zu vereinfachen:

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

Diese Klasse speichert eine Instanz von sich selbst in der ASP.NET-Sitzung und ermöglicht es Ihnen, von jeder Klasse aus typsicher auf Ihre Sitzungseigenschaften zuzugreifen, z. B.: Z.

int loginId = MySession.Current.LoginId;

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

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

Dieser Ansatz hat mehrere Vorteile:

  • es erspart dir viel typgießen
  • Sie müssen in Ihrer gesamten Anwendung keine fest codierten Sitzungsschlüssel verwenden (z. B. Sitzung ["loginId"]].
  • Sie können Ihre Sitzungselemente dokumentieren, indem Sie XML-Dokumentkommentare zu den Eigenschaften von MySession hinzufügen
  • Sie können Ihre Sitzungsvariablen mit Standardwerten initialisieren (z. B. sicherstellen, dass sie nicht null sind).
M4N
quelle
6
Es ist nicht erforderlich, Code zu schreiben. Verwenden Sie ihn wie in der Antwort gezeigt. Beispiel: "public int LoginId {get; set;}" -> Dies wird als automatische Eigenschaft bezeichnet.
M4N
4
Wenn Sie .net 3.x verwenden, können Sie automatische Eigenschaften verwenden, wie in meinem Code gezeigt. Mit .net 2.x / 1.x ist dies nicht verfügbar und Sie müssen den Getter / Setter Ihrer Eigenschaften selbst implementieren: private int _loginId; public int LoginId {get {return _loginId; } set {_loginId = value; }}
M4N
2
Sieht jetzt cool aus, ich glaube, ich habe die Antwort auf mein Problem erhalten, und ich benutze schon immer Ihren Weg. Es ist sehr sauber und einfach, alle meine Sitzungsvariablen an einem Ort zu verwalten. Danke @Martin, du bist super.
Prashant
23
@ M4N, wünschte ich könnte etwas mehr Dankbarkeit ausdrücken als eine +1. Dies ist meine bevorzugte Art, mit der Sitzung / dem Cache in meinen Projekten umzugehen. Mein Code dankt Ihnen buchstäblich.
Brandon Boone
4
@Kristopher Während die 'Current'-Eigenschaft statisch ist, ist die zurückgegebene Instanz von MySession nicht ... also ist es in Ordnung. Statische Methoden und Eigenschaften können auf diese Weise sicher verwendet werden.
Darren
104

Greifen Sie über die Threads HttpContext auf die Sitzung zu: -

HttpContext.Current.Session["loginId"]
AnthonyWJones
quelle
Vielen Dank Anthony für diesen einfachen Schritt.
Kings
Vielen Dank Anthony, + 1 dafür
Owais Qureshi
Vielen Dank. Vergessen, was der Namespace war :)
Anthony Horne
@AnthonyWJones Ich habe Ihre Methode verwendet, habe aber ein Problem. Können Sie mir erklären, wo ich falsch liege
?
und wenn Sie in HttpSessionStateBase konvertieren möchten: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/…
sobelito
24

Das Problem mit der vorgeschlagenen Lösung besteht darin, dass einige im SessionState integrierte Leistungsmerkmale beeinträchtigt werden können, wenn Sie einen Sitzungsspeicher außerhalb des Prozesses verwenden. (entweder "State Server Mode" oder "SQL Server Mode"). In oop-Modi müssen die Sitzungsdaten am Ende der Seitenanforderung serialisiert und am Anfang der Seitenanforderung deserialisiert werden, was kostspielig sein kann. Um die Leistung zu verbessern, versucht der SessionState, nur das zu deserialisieren, was von der ersten Deserialisierung der Variablen beim ersten Zugriff benötigt wird, und nur die geänderten Variablen neu zu serialisieren und zu ersetzen. Wenn Sie eine Menge Sitzungsvariablen haben und diese alle in eine Klasse verschieben, wird im Wesentlichen alles in Ihrer Sitzung bei jeder Seitenanforderung, die die Sitzung verwendet, deserialisiert, und alles muss erneut serialisiert werden, selbst wenn nur 1 Eigenschaft geändert wurde, weil sich die Klasse geändert hat. Nur etwas zu beachten, wenn Sie viel Sitzung und einen oop-Modus verwenden.

Ernie
quelle
4
+1 für das Auffrischen. Wenn Sie InProc for Session nicht verwenden, ist Ernie zu 100% korrekt. InProc ist ohnehin sehr eingeschränkt, da es keine Webfarms unterstützt und beim Neustart der Anwendung verloren geht. Beachten Sie, dass wir nach Leistungskosten eine Prämie von 20% für die Verwendung des State Server-Modus erwarten und zusätzlich Serialisierungskosten hinzukommen. Wie Sie sich vorstellen können, kann dies teuer werden. Sie können einen Teil des Serialisierungsaufwands vermeiden, indem Sie sich an primitive Typen halten (z. B. int, string, char, byte usw.). Benutzerdefinierte Objekte werden mit Serialisierung konfrontiert. Benutzer aufgepasst.
Zack Jannsen
+1 Guter Punkt. Eine Änderung, die die beiden Konzepte verbinden würde, wäre, dass jede Eigenschaft in dieser benutzerdefinierten "Sitzungs" -Klasse die asp.net-Sitzung selbst anstelle eines großen Objekts in der Sitzung aufruft. Sie müssen das Typ-Casting durchführen, das durch den Ansatz von @ M4N vermieden wird, aber es lohnt sich möglicherweise, wenn Sie jedes Mal nur einen Teil der Sitzung lesen.
Eol
12

Die vor mir vorgelegten Antworten bieten geeignete Lösungen für das Problem. Ich halte es jedoch für wichtig zu verstehen, warum dieser Fehler auftritt:

Die SessionEigenschaft von Pagegibt eine Instanz vom Typ HttpSessionStaterelativ zu dieser bestimmten Anforderung zurück. Page.Sessionist eigentlich gleichbedeutend mit anrufen Page.Context.Session.

MSDN erklärt, wie dies möglich ist:

Da ASP.NET-Seiten einen Standardverweis auf den System.Web-Namespace (der die HttpContextKlasse enthält ) enthalten, können Sie auf die Mitglieder HttpContexteiner ASPX-Seite ohne den vollständig qualifizierten Klassenverweis verweisen HttpContext.

Wenn Sie jedoch versuchen, innerhalb einer Klasse in App_Code auf diese Eigenschaft zuzugreifen, steht Ihnen die Eigenschaft nur zur Verfügung, wenn Ihre Klasse von der Seitenklasse abgeleitet ist.

Meine Lösung für dieses häufig auftretende Szenario besteht darin, dass ich niemals Seitenobjekte an Klassen übergebe . Ich würde lieber die erforderlichen Objekte aus der Seite Sitzung extrahieren und sie je nach Fall in Form einer Namens-Wert-Sammlung / Array / Liste an die Klasse übergeben.

Cerebrus
quelle
Das ist eine großartige Erklärung, es hat mir geholfen +1 dafür :)
Owais Qureshi
1

Ich hatte den gleichen Fehler, weil ich versucht habe, Sitzungsvariablen innerhalb einer benutzerdefinierten Sitzungsklasse zu bearbeiten.

Ich musste den aktuellen Kontext (system.web.httpcontext.current) an die Klasse übergeben, und dann hat alles gut geklappt.

MA

MunsterMan
quelle
1

Im asp.net-Kern funktioniert dies anders:

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

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

Matty
quelle
0

Dies sollte sowohl für die Anwendung als auch für den Entwickler effizienter sein.

Fügen Sie Ihrem Webprojekt die folgende Klasse hinzu:

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

}

Hier ist die Implementierung:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Captain America
quelle