webentwicklung-frage-antwort-db.com.de

Sitzungsvariablen in ASP.NET MVC

Ich schreibe eine Webanwendung, mit der ein Benutzer zu mehreren Webseiten auf der Website navigieren kann, um bestimmte Anforderungen zu erfüllen. Alle Informationen, die der Benutzer eingibt, werden in einem von mir erstellten Objekt gespeichert. Das Problem ist, dass ich auf dieses Objekt von jedem Teil der Website aus zugreifen muss und nicht wirklich weiß, wie ich das am besten erreichen kann. Ich weiß, dass eine Lösung darin besteht, Sitzungsvariablen zu verwenden, aber ich weiß nicht, wie ich sie in asp .net MVC verwenden soll. Und wo würde ich eine Sitzungsvariable deklarieren? Gibt es einen anderen Weg?

167
Draco

Ich würde denken, dass Sie darüber nachdenken möchten, ob die Dinge wirklich in einen Sitzungszustand gehören. Dies ist etwas, was ich hin und wieder mache und es ist eine nette, stark typisierte Herangehensweise an das Ganze, aber Sie sollten vorsichtig sein, wenn Sie Dinge in den Sitzungskontext stellen. Nicht alles sollte da sein, nur weil es einem Benutzer gehört.

hängen Sie in global.asax das Ereignis OnSessionStart ein

void OnSessionStart(...)
{
    HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}

Überall im Code, wo die Eigenschaft HttpContext.Current! = Null ist, können Sie dieses Objekt abrufen. Ich mache das mit einer Erweiterungsmethode.

public static MySessionObject GetMySessionObject(this HttpContext current)
{
    return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}

Auf diese Weise können Sie Code eingeben

void OnLoad(...)
{
    var sessionObj = HttpContext.Current.GetMySessionObject();
    // do something with 'sessionObj'
}
123
John Leidegren

Die Antwort hier ist richtig, ich hatte jedoch Schwierigkeiten, sie in einer ASP.NET MVC 3-App zu implementieren. Ich wollte auf ein Sitzungsobjekt in einem Controller zugreifen und konnte nicht herausfinden, warum ich immer wieder die Meldung "Instanz wurde nicht auf eine Instanz eines Objektfehlers festgelegt" erhielt. Was mir aufgefallen ist, ist, dass in einem Controller, als ich versuchte, auf die Sitzung zuzugreifen, indem ich Folgendes ausführte, dieser Fehler weiterhin auftrat. Dies liegt daran, dass this.HttpContext Teil des Controller-Objekts ist.

this.Session["blah"]
// or
this.HttpContext.Session["blah"]

Was ich jedoch wollte, war der HttpContext, der Teil des System.Web-Namespace ist, da dies derjenige ist, den die Antwort oben für Global.asax.cs vorschlägt. Also musste ich explizit Folgendes tun:

System.Web.HttpContext.Current.Session["blah"]

das hat mir geholfen, nicht sicher, ob ich etwas getan habe, das nicht M.O. hier in der nähe, aber ich hoffe es hilft jemandem!

46
Tomasz Iniewicz

Da ich nicht gerne "HTTPContext.Current.Session" über den Ort sehe, verwende ich ein Singleton-Muster, um auf Sitzungsvariablen zuzugreifen. Dadurch erhalten Sie einen einfachen Zugriff auf stark typisierte Datenmengen.

[Serializable]
public sealed class SessionSingleton
{
    #region Singleton

    private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";

    private SessionSingleton()
    {

    }

    public static SessionSingleton Current
    {
        get
        {
            if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
            {
                HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
            }

            return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
        }
    }

    #endregion

    public string SessionVariable { get; set; }
    public string SessionVariable2 { get; set; }

    // ...

dann können Sie von überall auf Ihre Daten zugreifen:

SessionSingleton.Current.SessionVariable = "Hello, World!";
21
Dead.Rabit

Wenn Sie asp.net mvc verwenden, können Sie auf einfache Weise auf die Sitzung zugreifen.

Von einem Controller:

{Controller}.ControllerContext.HttpContext.Session["{name}"]

Aus einer Sicht:

<%=Session["{name}"] %>

Dies ist definitiv nicht der beste Weg, um auf Ihre Sitzungsvariablen zuzugreifen, aber es ist ein direkter Weg. Gehen Sie daher vorsichtig vor (vorzugsweise während des Rapid Prototyping) und verwenden Sie einen Wrapper/Container und OnSessionStart, wenn dies angemessen ist.

HTH

14
robertz

Nun, meiner Meinung nach ..

  1. verweisen Sie niemals auf eine Sitzung in Ihrer Ansicht/Masterseite
  2. minimieren Sie Ihren Sitzungsverbrauch. MVC stellt hierfür TempData obj zur Verfügung. Hierbei handelt es sich im Grunde um eine Sitzung, die für einen einzelnen Trip zum Server ausgeführt wird.

In Bezug auf # 1 habe ich eine stark typisierte Master-Ansicht, die eine Eigenschaft für den Zugriff auf alle Objekte des Session-Objekts hat

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

AdminViewModel<TModel> : AdminViewModel where TModel : class
{
   TModel Content
}

und dann...

ViewPage<AdminViewModel<U>>
13
E Rolnicki

Es gibt 3 Möglichkeiten, dies zu tun.

  1. Sie können direkt auf HttpContext.Current.Session

  2. Du kannst HttpContextBase verspotten

  3. Erstellen Sie eine Erweiterungsmethode für HttpContextBase

Ich bevorzuge den 3. Weg. Dieser Link ist eine gute Referenz.

Get/Set HttpContext-Sitzungsmethoden in BaseController vs. Mocking HttpContextBase zum Erstellen von Get/Set-Methoden

7

Ich weiß zwar nichts über asp.net mvc, aber das ist, was wir auf einer normalen .net-Website tun sollten. Es sollte auch für asp.net mvc funktionieren.

YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}

Sie würden dies in eine Methode für den einfachen Zugriff einfügen. HTH

7
DotNET

Tolle Antworten von den Jungs, aber ich möchte Sie davor warnen, sich immer auf die Session zu verlassen. Dies ist schnell und einfach zu bewerkstelligen und würde natürlich funktionieren, wäre aber nicht unter allen Umständen großartig.

Zum Beispiel, wenn Sie in ein Szenario geraten, in dem Ihr Hosting die Sitzungsnutzung nicht zulässt, wenn Sie sich in einer Webfarm befinden oder im Beispiel einer freigegebenen SharePoint-Anwendung.

Wenn Sie nach einer anderen Lösung suchen, können Sie ein IOC-Container wie Castle Windsor verwenden, eine Anbieterklasse als Wrapper erstellen und dann eine Instanz Ihrer Klasse mit dem beibehalten je nach Anforderung oder Sitzungslebensstil.

Das IOC würde sicherstellen, dass jedes Mal dieselbe Instanz zurückgegeben wird.

Komplizierter ja, wenn Sie eine einfache Lösung benötigen, verwenden Sie einfach die Sitzung.

Hier sind einige Implementierungsbeispiele aus Interesse.

Mit dieser Methode können Sie eine Anbieterklasse wie folgt erstellen:

public class CustomClassProvider : ICustomClassProvider
{
    public CustomClassProvider(CustomClass customClass)
    { 
        CustomClass = customClass;
    }

    public string CustomClass { get; private set; }
}

Und registriere es so ähnlich wie:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
            Component.For<ICustomClassProvider>().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }
6
shenku

Ich greife auf Sitzungen zu, indem ich eine Hilfsklasse schreibe, die die verschiedenen Feldnamen und ihre Typen kapselt. Ich hoffe dieses Beispiel hilft:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;

namespace dmkp
{
    /// <summary>
    /// Encapsulates the session state
    /// </summary>
    public sealed class LoginInfo
    {
        private HttpSessionState _session;
        public LoginInfo(HttpSessionState session)
        {
            this._session = session;
        }

        public string Username
        {
            get { return (this._session["Username"] ?? string.Empty).ToString(); }
            set { this._session["Username"] = value; }
        }

        public string FullName
        {
            get { return (this._session["FullName"] ?? string.Empty).ToString(); }
            set { this._session["FullName"] = value; }
        }
        public int ID
        {
            get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
            set { this._session["UID"] = value; }
        }

        public UserAccess AccessLevel
        {
            get { return (UserAccess)(this._session["AccessLevel"]); }
            set { this._session["AccessLevel"] = value; }
        }

    }
}
5
Daniel

Sie können ViewModelBase als Basisklasse für alle Modelle verwenden. Diese Klasse übernimmt das Abrufen von Daten aus der Sitzung

class ViewModelBase 
{
  public User CurrentUser 
  {
     get { return System.Web.HttpContext.Current.Session["user"] as User };
     set 
     {
        System.Web.HttpContext.Current.Session["user"]=value; 
     }
  }
}

Sie können eine Erweiterungsmethode für HttpContextBase schreiben, um mit Sitzungsdaten umzugehen

T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null) 
{
    if(context.Session[key]!=null) 
    {
        return (T) context.Session[key];
    }
  else if(getFromSource!=null) 
  {
    var value = getFromSource();
   context.Session[key]=value; 
   return value; 
   }
  else 
  return null;
}

Verwenden Sie dies wie unten im Controller

User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db  }); 

Das zweite Argument ist optional. Es wird verwendet, um Sitzungsdaten für diesen Schlüssel zu füllen, wenn in der Sitzung kein Wert vorhanden ist.

4
Ajay Kelkar