In un articolo precedente abbiamo realizzato un carrello della spesa, utilizzando l'oggetto Profile
per utenti non ancora autenticati.
Il passo successivo nell'implementazione di un'applicazione di e-commerce è quello di trasferire le informazioni associate all'utente non autenticato, che visitando il sito ha riempito il suo carrello della spesa, ad un utente autenticato, in quanto l'utente anonimo, per ritirare la merce dovrà autenticarsi. Vediamo come fare lavorando su un esempio.
Prendiamo l'applicazione che abbiamo sviluppato nell'articolo precedente, e rinominiamola "TrasferireProfilo".
Aggiungiamo il file "Global.asax".
Per chi non lo sapesse, il file "Global.asax" è un file facoltativo che può essere inserito in un'applicazione ASP.NET per gestire eventi a livello di applicazione o di sessione. Il "Global.asax" va messo nella cartella principale dell'applicazione e non può essere editato o visualizzato con il browser mediante una richiesta URL.
Ci serve il "Global.asax" per poter gestire l'evento ProfileModule.MigrateAnonymous
che viene generato da un'applicazione ASP.NET 2.0 quando un utente anonimo, che possiede un profilo, effettua l'accesso, cioè si autentifica.
Sarà sempre sul Global.asax che implementeremo il gestore di quest'evento. Quindi, con il VWD, aggiungiamo alla nostra applicazione l'Elemento denominato "Classe di Applicazione Globale".
Troveremo già impostati i metodi: Application_Start
, Application_End
, Application_Error
, Session_Start
e Session_End
; questi metodi servono a gestire i relativi eventi a livello di applicazione e sessione. Lasciamo stare i metodi già impostati ed aggiungiamo quello che ci interessa.
Listato 1. Profile_OnMigrateAnonymous sul Global.asax
void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)
{
// otteniamo il profilo dell'utente anonimo
ProfileCommon anonymousProfile = Profile.GetProfile(args.AnonymousID);
// trasferiamo il carrello
Profile.Carrello = anonymousProfile.Carrello;
// cancelliamo il profilo anonimo
ProfileManager.DeleteProfile(args.AnonymousID);
// cancelliamo l'utente anonimo dal database
Membership.DeleteUser(args.AnonymousID);
// cancelliamo il cookie dell'utente anonimo
AnonymousIdentificationModule.ClearAnonymousIdentifier();
}
Come possiamo notare dal listato, la prima cosa che facciamo, è l'estrazione del profilo dell'utente anonimo mediante l'uso della proprietà AnonymousID
. Poi trasferiamo il carrello della spesa, cancelliamo il profilo anonimo e l'utente anonimo, che non ci servono più, ed eliminiamo il cookie associato.
Il Profile_OnMigrateAnonymous
sul Global.asax si metterà in funzione quando l'utente esegue il Login, quindi per il trasferimento del profilo abbiamo fatto tutto.
Realizziamo ora una pagina che ci consenta di visualizzare il contenuto del carrello della spesa in modo che l'utente possa controllare quello che sta acquistando.
Nella classe Articolo
abbiamo messo le variabili di istanza identificatore
e quantità
che sono le informazioni minime ma sufficienti, a descrivere completamente l'articolo. Infatti per avere la descrizione completa, basterebbe accedere al database con l'identificatore che è univoco per ogni articolo. Nel nostro esempio però, non disponendo di un database, avendo semplificato questo aspetto, abbiamo posizionato due articoli sulla pagina Prodotti.aspx
con le informazioni: identificatore, descrizione e prezzo.
Ora, per visualizzare il carrello, ci conviene portarci dietro anche informazioni come descrizione e prezzo. Ciò per avere una visione completa degli articoli scelti.
Operiamo quindi una piccola modifica alla classe Articolo
inserendo fra le variabili di istanza anche descrizione
e prezzo
.
Listato 2. Aggiunta di informazioni alla classe Articolo
public class Articolo
{
public String identificatore;
public String descrizione;
public String prezzo;
public int quantità;
// costruttore di default necessario per la serializzazione
public Articolo() { }
// costruttore da utilizzare
public Articolo(String identificatore, String descrizione, String prezzo, int quantità)
{
this.identificatore = identificatore;
this.descrizione = descrizione;
this.prezzo = prezzo;
this.quantità = quantità;
}
}
Aggiorniamo quindi tutti i punti dell'applicazione in cui viene chiamato il costruttore della classe Articolo
.
Il costruttore modificato viene chiamato solo nella classe Carrello
. Operiamo la modifica:
Listato 3. Modifica alla classe Carrello
[XmlInclude(typeof(Articolo))]
public class Carrello
{
public ArrayList articoli;
public Carrello()
{
articoli = new ArrayList();
}
public void aggiungiArticolo(String identificatore, String descrizione, String prezzo, int quantità)
{
articoli.Add(new Articolo(identificatore, descrizione, prezzo, quantità));
}
}
Modifichiamo ora tutti i punti dell'applicazione in cui viene chiamato il metodo aggiungiArticolo
poiché ne abbiamo modificato la firma. Tale metodo viene chiamato in ButtonAggiungi_Click
della Prodotti.aspx.cs
. Operiamo la modifica:
Listato 4. Modifica a ButtonAggiungi_Click in Prodotti.aspx.cs
protected void ButtonAggiungi_Click(object sender, EventArgs e)
{
Carrello carrelloUtente = Profile.Carrello;
switch (((Button)sender).ID)
{
case "Button1Aggiungi":
carrelloUtente.aggiungiArticolo(Label1Id.Text, Label2Des.Text, Label3Prezzo.Text, 1);
break;
case "Button2Aggiungi":
carrelloUtente.aggiungiArticolo(Label4Id.Text, Label5Des.Text, Label6Prezzo.Text, 1);
break;
}
Profile.Carrello = carrelloUtente;
}
Realizziamo ora la pagina per visualizzare il carrello della spesa.
Possiamo inserire la pagina all'interno della cartella Autenticati
in modo che l'utente, per vederla, debba effettuare il Login, e quindi avvenga il trasferimento del profilo dall'utente anonimo all'utente autenticato.
Chiamiamo la pagina Acquisti.aspx
.
In Acquisti.aspx
mettiamo la Label Label1Msg
mentre nella Acquisti.aspx.cs
, mettiamo una chiamata al metodo visualizzaSpesa
nel Page_Load
.
Implementiamo ora il metodo visualizzaSpesa
.
Qui dobbiamo visualizzare tutti gli articoli presenti nel carrello dell'utente che si è appena autenticato. Il trasferimento del carrello, in seguito all'autenticazione, viene gestito nel Global.asax
che abbiamo già sistemato.
La prima cosa che dobbiamo fare è definire un riferimento all'oggetto Carrello
incluso nel profilo dell'utente. Poiché la classe Carrello
ha al suo interno un ArrayList
che contiene oggetti di tipo Articolo
, possiamo utilizzare la proprietà Count
dell'ArrayList
per verificare se il carrello è vuoto oppure no. Se il carrello contiene uno o più articoli, li estraiamo con l'istruzione foreach
applicata all'ArrayList
.
Listato 5. Il metodo visualizzaSpesa() in Acquisti.aspx.cs
protected void visualizzaSpesa()
{
Carrello carrello = Profile.Carrello;
if (carrello.articoli.Count != 0)
{
Label1Msg.Text = "Il tuo carrello contiene: " + "<br />";
Label1Msg.Text += "====================" + "<br />";
foreach (Articolo articolo in carrello.articoli)
{
Label1Msg.Text += "Articolo numero...: " + articolo.identificatore + "<br />";
Label1Msg.Text += "Descrizione.......: " + articolo.descrizione + "<br />";
Label1Msg.Text += "Prezzo............: " + articolo.prezzo + "<br />";
Label1Msg.Text += "Quantità..........: " + articolo.quantità.ToString() + "<br />";
Label1Msg.Text += "====================" + "<br />";
}
}
else
Label1Msg.Text = "Non hai effettuato acquisti." + "<br />";
}
Per semplificarci la vita in fase di test, in Prodotti.aspx
mettiamo un link ad Acquisti.aspx
ed in Acquisti.aspx
mettiamo un link a Prodotti.aspx
in modo che si possa navigare tra le due pagine.
Se nella nostra applicazione non è presente alcun utente, inseriamone almeno uno con il WAT.
Ora, per fare un test, editiamo le tabelle aspnet_Profile
ed aspnet_Users
in modo da poter monitorare gli utenti presenti ed i profili.
Supponiamo di aver inserito mediante il WAT l'utente Pippo.
Su aspnet_Users
avremo:
Se visualizziamo aspnet_Profile
notiamo che è vuota, come è lecito aspettarsi, in quanto nessun utente si è ancora collegato e quindi nessun profilo è stato creato.
Ora editiamo la pagina Prodotti.aspx
e premiamo F5.
Scegliamo i due prodotti cliccando sul relativo pulsante "Aggiungi al carrello".
Se, in questo momento, senza chiudere il browser verifichiamo il contenuto delle due tabelle: notiamo la presenza dell'utente anonimo sulla aspnet_Users
e del suo profilo con il carrello sulla aspnet_Profile
.
Per verificare che il carrello appartiene all'utente anonimo possiamo controllare lo UserId
che deve coincidere per lo stesso utente nelle due tabelle.
Siamo rimasti per un po' con il browser aperto dopo aver effettuato la scelta dei prodotti:
Adesso clicchiamo su "Visualizza acquisti" che ci conduce alla pagina per visualizzare il carrello e ci obbliga ad effettuare il Login.
Effettuiamo il Login con l'utente Pippo.
Ci viene visualizzato il carrello della spesa, che coincide con i prodotti che abbiamo scelto quando eravamo ancora anonimi:
Se ora andiamo a vedere che cosa è successo sulle due tabelle notiamo che su aspnet_Users
non c'è più l'utente anonimo, in quanto lo cancelliamo con il Global.asax
quando non ci serve più, e su aspnet_Profile
il carrello è passato all'utente autenticato come possiamo verificare confrontando gli UserId
. Il profilo dell'utente anonimo è stato inoltre eliminato.
L'esempio sviluppato in questo articolo, privato del database per motivi di spazio, può essere scaricato da qui.