2009-05-27 24 views
7

Ho un'applicazione che è stata scritta in ASP.NET vaniglia che vorrei trasferire su ASP.NET MVC.ASP.NET MVC Session vs Global vs Cache

Io, tuttavia, sono confuso circa il posto giusto per mantenere gli oggetti. Ho bisogno di persistere per un paio di ragioni:

  1. Vorrei tutto per avere una connessione al database singolo, avvolto in un "repository" o oggetto di stile "manager".
  2. Ogni utente ha un oggetto utente che deve essere salvato per ogni sessione.

Normalmente, vorrei dire che il numero 1 verrebbe salvato come elemento statico nel Globals.asax che può essere colpito utilizzando Global.Repository o simile.

E normalmente direi che # 2 dovrebbe essere una proprietà con un backing store di sessione da qualche parte nella classe base delle pagine.

Ora il motivo per cui sono confuso è che ho sentito che le sessioni sono cambiate in MVC e che Global.asax non contiene più la stessa classe. Inoltre, il concetto di pagine è stato rimosso, quindi aggiungere una proprietà alla classe base di un controller sembra ... sbagliato.

Cosa si dice?

risposta

10

Il database verrà inserito in una classe base per i controller. Questa classe base dovrebbe estendere il controller e tutti i controller dovrebbero estendere la classe base. Ecco un piccolo esempio:

public class BaseController : Controller 
{ 
    private AuthServices _auth; 
    private LogHelper _log; 
    private Repository _repository; 

    /// <summary> 
    /// <see cref="AuthServices"/> 
    /// </summary> 
    protected AuthServices Authorization 
    { 
     get { return _auth ?? (_auth = new AuthServices()); } 
    } 

    /// <summary> 
    /// <see cref="LogHelper"/> 
    /// </summary> 
    protected LogHelper Log 
    { 
     get { return _log ?? (_log = new LogHelper()); } 
    } 

    /// <summary> 
    /// <see cref="Repository"/> 
    /// </summary> 
    protected Repository Repository 
    { 
     get { return _repository ?? (_repository = new Repository()); } 
    } 
} 

Si noti l'istanza lazy. Questo mi permette di entrare di nascosto prima di eseguire i test e impostare i miei campi privati ​​con mock.

Per quanto riguarda la sessione, l'oggetto Utente può ancora essere salvato nella sessione proprio come in un'applicazione ASP.NET tradizionale. Quasi tutto è ancora in circolazione (Response, Cache, Session, ecc.), Ma alcuni di essi sono stati integrati con le classi di System.Web.Abstractions in modo che possano essere presi in giro per il test. Si comportano tutti allo stesso modo, anche se non dovresti usare alcuni di essi nel loro ruolo tradizionale (ad esempio, non Response.Redirect, restituisci un ActionResult come RedirectToRouteResult che esegue il tuo reindirizzamento).

Per quanto riguarda il ragionamento dietro le vostre domande ....

Non lo stress su una singola connessione db. A seconda dell'implementazione, potrebbe anche essere una cattiva idea, in quanto le richieste possono essere reciproche. Apri il tuo collegamento, usalo e disponilo/chiudilo quando hai finito.

Inoltre, uno dei più grandi cambiamenti apportati da MVC è il rifiuto del modello stateful che il tradizionale ASP.NET ha tentato di portare allo sviluppo web. Tutto questo quadro e il panorama non esistono più (non prestare attenzione all'uomo dietro la tenda). Meno lo stato si tiene sul meno complesso e più robusto è la tua applicazione web. Provalo, potrebbe piacerti.

+1

"Notate l'istanza pigra, che mi permette di entrare di nascosto prima di eseguire test e impostare i miei campi privati ​​con mock". Perché non usare IoC? –

+1

Baby steps ...... Dovresti rispondere con un esempio di questo. – Will

+1

Uso effettivamente il pool di connessioni. Comunque, grazie. Questo è quasi esattamente quello che stavo progettando, buono a sapere che sto seguendo abbastanza vicino alle migliori pratiche. –

2

Le sessioni non sono state modificate in MVC. La classe GlobalApplication in Global.asax esiste ancora. Esistono anche pagine che vorresti fare riferimento a un repository in un controller piuttosto che in una pagina. L'aggiunta di una proprietà a una classe di controller di base va bene; Lo faccio tutto il tempo.

4

Se si utilizzano le sessioni, si consiglia di tenere una classe di sessione, in modo che sia necessario specificare il nome della stringa solo una volta nel codice e questo vi darà anche IntelliSence.

public static class SessionHandler 
{ 
    // User Values 
    private static string _userID = "UserID"; 
    private static string _userRole = "UserRole"; 

    public static string UserID 
    { 
     get 
     { 
      if (HttpContext.Current.Session[SessionHandler._userID] == null) 
      { return string.Empty; } 
      else 
      { return HttpContext.Current.Session[SessionHandler._userID].ToString(); } 
     } 
     set 
     { HttpContext.Current.Session[SessionHandler._userID] = value; } 

    } 

    public static string UserRole 
    { 
     get 
     { 
      if (HttpContext.Current.Session[SessionHandler._userRole] == null) 
      { return string.Empty; } 
      else 
      { return HttpContext.Current.Session[SessionHandler._userRole].ToString(); } 
     } 
     set 
     { HttpContext.Current.Session[SessionHandler._userRole] = value; } 

    } 
} 
+0

Mi piace, ma occorrerebbe creare un'istanza per ciascun controller. Preferirei che tutti i controller di una sessione condividessero oggetti basati sulla sessione, quindi li inserirò come proprietà in una classe BaseController. –

1

È possibile creare un raccoglitore modello per incapsulare lo stato.

(Vedi il libro MVC di Steve Sanderson sulla sua implementazione carrello della spesa)

Con il modello legante, si ha accesso al controllerContext - che ha il HttpContext.