Domanda

Sto scrivendo un'applicazione web che permette all'utente di navigare su più pagine Web all'interno del sito web facendo alcune richieste. Tutte le informazioni che gli ingressi di utente verranno memorizzati in un oggetto che ho creato. Il problema è che ho bisogno di questo oggetto a cui accedere da qualsiasi parte del sito web e io non so davvero il modo migliore per ottenere questo risultato. So che una soluzione è quella di utilizzare le variabili di sessione, ma non so come usarli in asp .net MVC. E dove dovrei dichiarare una variabile di sessione? C'è qualche altro modo?

È stato utile?

Soluzione

Vorrei pensare si vorrà pensare se le cose appartengono davvero in uno stato di sessione. Questo è qualcosa che mi ritrovo a fare di tanto in tanto ed è un bel approccio fortemente tipizzato a tutta la cosa, ma si deve fare attenzione quando mettere le cose nel contesto di sessione. Non tutto dovrebbe essere lì solo perché appartiene a qualche utente.

in global.asax associare l'evento OnSessionStart

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

Da qualsiasi codice in cui la proprietà HttpContext.Current! = Null è possibile retrive quell'oggetto. Lo faccio con un metodo di estensione.

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

In questo modo è possibile in codice

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

Altri suggerimenti

La risposta qui è corretta, ho comunque lottato per la sua attuazione in un ASP.NET MVC 3 app. Volevo accedere a un oggetto di sessione in un controllore e non riuscivo a capire perché ho continuato a ottenere un "grado non impostato a un'istanza di un errore di oggetto". Quello che ho notato è che in un controller quando ho cercato di accedere alla sessione facendo quanto segue, ho continuato a ottenere tale errore. Ciò è dovuto al fatto che this.HttpContext è parte dell'oggetto Controller.

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

Tuttavia, quello che volevo era il HttpContext che fa parte del namespace System.Web perché questo è quello che la risposta sopra suggerisce di utilizzare in Global.asax.cs. Così ho dovuto fare in modo esplicito il seguente:

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

questo mi ha aiutato, non so se ho fatto tutto ciò che non è M.O. da queste parti, ma spero che aiuta qualcuno!

Perché non amo vedere "HTTPContext.Current.Session" circa il posto, io uso un pattern Singleton per accedere alle variabili di sessione, ti dà un facile accesso fortemente tipizzato sacchetto dei dati.

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

    // ...

, allora è possibile accedere ai dati da qualsiasi luogo:

SessionSingleton.Current.SessionVariable = "Hello, World!";

Se si sta utilizzando asp.net MVC, ecco un modo semplice per accedere alla sessione.

Da un controller:

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

Da una vista:

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

Questo non è sicuramente il modo migliore per accedere ai variabili di sessione, ma è un percorso diretto. In modo da utilizzare con cautela (preferibilmente durante prototipazione rapida), e utilizzare un involucro / contenitore e OnSessionStart quando diventa opportuno.

HTH

Bene, IMHO ..

  1. mai fare riferimento a una sessione all'interno della vostra pagina di visualizzazione / master
  2. ridurre al minimo l'useage of Session. MVC prevede TempData obj per questo, che è fondamentalmente una sessione che vive per un singolo viaggio al server.

Per quanto riguarda la 1 #, ho un Master View fortemente tipizzato che ha una proprietà per accedere qualunque sia l'oggetto Session rappresenta .... nel mio caso il stongly digitato Master View è generico, che mi dà una certa flessibilità per quanto riguarda il forte digitato Vista Pagine

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

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

e poi ...

ViewPage<AdminViewModel<U>>

Anche se io non so su asp.net MVC, ma questo è ciò che dobbiamo fare in un normale sito web .net. Dovrebbe funzionare per asp.net mvc anche.

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

Si potrebbe mettere questo all'interno di un metodo per un facile accesso. HTH

Ci sono 3 modi per farlo.

  
      
  1. È possibile accedere direttamente HttpContext.Current.Session

  2.   
  3. È possibile Mock HttpContextBase

  4.   
  5. Creare un metodo di estensione per HttpContextBase

  6.   

Io preferisco terzo collegamento way.This è buon riferimento.

get / set HttpContext Metodi di sessione in BaseController vs Mocking HttpContextBase per creare metodi get / set

Grandi risposte da ragazzi, ma io ti mettere in guardia contro basandosi sempre sulla sessione. E 'veloce e facile da fare così, e, naturalmente, avrebbe funzionato, ma non sarebbe bello in tutte le cicrumstances.

Per esempio, se si esegue in uno scenario in cui il tuo hosting non permette l'uso della sessione, o se siete su una web farm, o l'esempio di un'applicazione di SharePoint condivisa.

Se si voleva una soluzione diversa si poteva guardare utilizzando un CIO Container come Castello di Windsor , la creazione di una classe di provider come un involucro e quindi mantenendo un'istanza della classe con il secondo richiesta o stile di vita della sessione seconda delle vostre esigenze.

Il CIO garantirebbe che la stessa istanza viene restituita ogni volta.

Più complicato sì, se avete bisogno di una soluzione semplice, basta utilizzare la sessione.

Ecco alcuni esempi di implementazione di seguito per interesse.

Con questo metodo si potrebbe creare una classe fornitore lungo le linee di:

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

    public string CustomClass { get; private set; }
}

E registrarlo qualcosa come:

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

Il mio modo di accedere a sessioni è quello di scrivere una classe di supporto che racchiude i vari nomi dei campi e le loro tipologie. Spero che questo esempio aiuta:

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

    }
}

È possibile utilizzare ViewModelBase come classe di base per tutti i modelli, questa classe si prenderà cura di tirare i dati dalla sessione

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

È possibile scrivere un metodo di estensione su HttpContextBase a che fare con i dati della sessione

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

Utilizzare questa come di seguito controller

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

Il secondo argomento è facoltativo verrà utilizzato dati di sessione di riempimento per quella chiave quando il valore non è presente in sessione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top