103 messaggi dal 14 aprile 2014
Buonasera a tutti.

Ho realizzato un area riservata (asp net MVC) dove alcuni utenti si collegano (autenticano) per effettuare attività di backoffice.

Ho la necessità di mantenere in sessione uno o più oggetti contententi tutti i dati dell'utente che si è autenticato (email, numero telefono, indirizzo, ...) per poterli leggere all'interno dell'area riservata *** senza aprire continue connessioni al database ***.

Ho cercato sui forum ma non mi è molto chiaro come fare e quali tecniche sono le più corrette per mantenere oggetti e dati in sessione.

Vorrei gentilmente qualche indicazione o spunto di partenza per poter poi proseguire correttamente.

grazie.

Filippo.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Filippo,
cerca di mettere tutte le proprietà in un solo oggetto, così sarà più facile da gestire. Per esempio creati una classe chiamata UserProfile tipo questa, che contenga tutte le proprietà di cui hai bisogno.
public class UserProfile
{
  public string Email { get; set; }
  public string Nome { get; set; }
  public string Indirizzo { get; set; }
}


Il piano è il seguente: se in una variabile di sessione come Session["UserProfile"] esiste già un'istanza di quella classe, allora la usiamo. Altrimenti, bisognerà interrogare il database per costruirla e poi la potremo assegnare alla stessa variabile di Sessione affinché sia disponibile in tutte le successive richieste.

E' semplice da fare ma l'obiettivo è quello di non avere questa logica tra i piedi in tutti i punti in cui ti serve accedere a quei dati.
Sarebbe bello se si potesse "ricevere" l'istanza di UserProfile come parametro di un'action, in modo che sia subito pronto da usare. Per esempio:
public ActionResult Index(UserProfile userProfile) {
  //Fai qualcosa con userProfile
}

Questo è possibile se ti scrivi un model binder personalizzato tipo il seguente:
public class UserProfileModelBinder : System.Web.Mvc.IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        //Mi assicuro che il tipo da risolvere sia UserProfile, ovvero la mia classe
        //in cui si trovano indirizzo, città, ecc...
        if (bindingContext.ModelType != typeof(UserProfile))
            return null;

        var identity = controllerContext.HttpContext.User.Identity;

        //Se l'utente è anonimo non posso ottenere il suo profilo
        if (!identity.IsAuthenticated)
            return null;

        //Vado a controllare se il profilo per caso è già stato cachato in sessione
        var session = controllerContext.HttpContext.Session;
        var userProfile = session["UserProfile"] as UserProfile;

        
        if (userProfile == null)
        {
            //Altrimenti lo vado a prendere dal db
            //Usando lo username come criterio
            var username = identity.Name;
            //Qui faccio la query al db
            var userProfileEstrattoDalDatabase = ...;
            // e poi lo mappo (o lo assegno) alla variabile userProfile
            userProfile = userProfileEstrattoDalDatabase;
            // lo assegno anche alla variabile di sessione, così che sarà disponibile alla prossima richiesta
            session["UserProfile"] = userProfile;
        }

        //Lo restituisco
        return userProfile;
    }
}


Non resta che registrarlo nel global.asax, all'interno del metodo Application_Start
System.Web.Mvc.ModelBinders.Binders.Add(typeof(UserProfile), new UserProfileModelBinder());


Ci sono ovviamente anche altri sistemi per ottenere il profilo dell'utente. Alcuni non sono neanche basati sulla sessione. Per esempio è possibile inserire le informazioni dell'utente (cifrate) direttamente all'interno del cookie di autenticazione (vengono chiamate claims), purché non siano troppe altrimenti il cookie comincia ad avere un certo peso.

Tu che meccanismo di autenticazione usi? ASP.NET Identity?

ciao,
Moreno
Modificato da BrightSoul il 21 agosto 2016 19.13 -

Enjoy learning and just keep making
103 messaggi dal 14 aprile 2014
Ciao Moreno.

Ti ringrazio per la risposta, capisco di essere davvero impreparato sui metodi di autenticazione e sto approfondendo.

Ho implementato il tuo suggerimento (uso della Session["UserProfile"]).

Ma il compilatore mi restituisce questo errore.

*** ErrorCS0535'UserProfileModelBinder' does not implement interface member 'IModelBinder.BindModel(ControllerContext, ModelBindingContext)' ***

Ho cercato informazioni su web ma non risolutive.

Ho regolarmente registrato in GLOBAL.ASAX Application_Start come da te indicato.

Ma l'errore persiste.

Cordiali saluti.

Filippo
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Filippo,


Ma il compilatore mi restituisce questo errore.
*** ErrorCS0535'UserProfileModelBinder' does not implement interface member 'IModelBinder.BindModel(ControllerContext, ModelBindingContext)' ***

Questo errore non è specifico di MVC o del ModelBinder ma, in generale, si verifica se una classe qualsiasi che dichiara di voler implementare un'interfaccia, come questa:
public class UserProfileModelBinder : System.Web.Mvc.IModelBinder

Poi, di fatto, non implementa fedelmente i membri definiti dall'interfaccia.
In questo caso specifico, il compilatore si lamenta che nella tua classe non c'è un metodo chiamato BindModel che accetta due parametri ControllerContext e ModelBindingContext.

Lì per lì, questo errore potrebbe destare confusione, perché in realtà nell'esempio che ti ho fornito questo metodo c'è, eccome.
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)


Bisogna anche dire che non ti ho specificato i namespace delle classi ControllerContext e ModelBindingContext. Infatti, ModelBindingContext si trova sia in System.Web.Mvc (che è il namespace che vogliamo) che in System.Web.ModelBinding (che non ci serve in questo caso).

Quindi prova a modificare il metodo così, almeno siamo espliciti sul tipo che vogliamo usare.
public object BindModel(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext) {
...
}


Comunque, non ti lasciar bloccare da un errore come questo. Visual Studio ti aiuta ad implementare correttamente le interfacce se fai tasto destro sul nome dell'interfaccia (IModelBinder in questo caso) e poi clicchi la prima voce (quella con la lampadina) e poi fai "Implementa interfaccia". Ti verrà generato il metodo corretto in cui mettere il codice.

Eccolo in un esempio:
https://jeremybytes.blogspot.it/2016/02/visual-studio-shortcuts-implementing.html

ciao,
Moreno

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.