Specifiche ASP.NET Starter Kit: Commerce Ottobre 2002 © 2002 Microsoft Corp. Tutti i diritti riservati. Le informazioni contenute nel presente documento costituiscono la soluzione attuale di Microsoft Corporation alle questioni sollevate alla data di pubblicazione. La risposta di Microsoft alle variazioni del mercato non deve essere interpretata come un impegno da parte della stessa, inoltre Microsoft non può garantire l’accuratezza delle informazioni fornite dopo la data di pubblicazione del presente documento. Questo documento è esclusivamente per scopi informativi. MICROSOFT ESCLUDE OGNI GARANZIA ESPRESSA O IMPLICITA PER LE INFORMAZIONI CONTENUTE IN QUESTO DOCUMENTO. Il rispetto di tutte le applicabili leggi in materia di copyright è esclusivamente a carico dell’utente. Fermi restando tutti i diritti coperti da copyright, nessuna parte di questo documento potrà comunque essere riprodotta o inserita in un sistema di riproduzione o trasmessa in qualsiasi forma e con qualsiasi mezzo (in formato elettronico, meccanico, su fotocopia, come registrazione o altro) per qualsiasi scopo, senza il permesso scritto di Microsoft Corporation. Microsoft può essere titolare di brevetti, domande di brevetto, marchi, copyright o altri diritti di proprietà intellettuale relativi all’oggetto del presente documento. Salvo quanto espressamente previsto in un contratto scritto di licenza Microsoft, la consegna del presente documento non implica la concessione di alcuna licenza su tali brevetti, marchi, copyright o altra proprietà intellettuale. Microsoft, Visual Studio, Windows, IntelliSense, Visual Basic, Visual C#, MSDN, Windows NT e JScript sono marchi o marchi registrati di Microsoft Corp. negli Stati Uniti e/o negli altri paesi. I nomi di prodotti e società citati nel presente documento possono essere marchi dei rispettivi proprietari. Microsoft Corp. • One Microsoft Way • Redmond, WA 98052-6399 • USA ASP.NET Starter Kit Pagina 1 di 20 ASP.NET Commerce Starter Kit: progetto e implementazione Vertigo Software, Inc. Ottobre 2002 Sommario: In questo articolo vengono descritti il progetto e le decisioni architetturali dell’applicazione Commerce Starter Kit. Viene inoltre effettuato un esame dettagliato della relativa implementazione. (20 pagine stampate) Panoramica Descrizione di Commerce Starter Kit Commerce Starter Kit è una vetrina e-commerce per la vendita di finti articoli da spionaggio. Nell’applicazione viene data dimostrazione delle operazioni di vendita online di base, nonché di funzioni quali il catalogo dei prodotti, l’autenticazione degli utenti e la relativa personalizzazione dell’applicazione, i carrelli della spesa e la verifica degli ordini. Nel Commerce Starter Kit vengono illustrate molte funzionalità offerte dalla tecnologia ASP.NET, tra cui: Supporto di esplorazione per browser Netscape e Internet Explorer Separazione netta dei contenuti html dal codice tramite controlli server Pagine di catalogo ad elevate prestazioni con l’ausilio del caching di output Accesso ai dati ADO.NET a tre livelli tramite stored procedure SQL Autenticazione dei form mediante un database per nome utente/password Servizi Web SOAP XML per acquisizione e stato degli ordini B2B In questo articolo si discuterà approfonditamente di Commerce Starter Kit, fornendone una descrizione dalla prospettiva dei realizzatori. Verrà inoltre illustrato il modo in cui è possibile utilizzare Commerce Starter Kit come modello per realizzare una vetrina e-commerce, esaminando molte delle funzionalità chiave dell’applicazione e le tecnologie utilizzate per realizzarle. Commerce Starter Kit è stato sviluppato nelle versioni in-line e code-behind. La versione SDK è codificata in-line ed è ottimizzata per il progetto ASP.NET Web Matrix Project e per .NET Framework SDK. La seconda versione è stata scritta utilizzando Microsoft® Visual Studio.NET™ secondo il modello di codifica code-behind. Entrambe le versioni contengono implementazioni scritte in C# e VB.NET. Architettura dell’applicazione Le applicazioni Web distribuite sono tradizionalmente progettate e realizzate su tre livelli logici: Livello di accesso al database (Database Access Layer - DAL) Livello di logica business (Business Logic Layer - BLL) Livello di presentazione (Presentation Layer) Il livello DAL fa riferimento al database vero e proprio, alle stored procedure e ai componenti che forniscono un’interfaccia con il database. Il livello BLL fa riferimento ai componenti che incapsulano tutta la logica business dell’applicazione. Il livello di presentazione, infine, fa riferimento alle pagine Web dell’applicazione. Realizzare applicazioni distribuite tramite le tecnologie .NET prevede l’adozione di architetture ben progettate di logica a tre livelli. Commerce Starter Kit è stato realizzato tenendo presente questo concetto, salvo un’unica eccezione. Per ridurre la complessità dell’applicazione, i livelli BLL e DAL sono stati fusi in un unico livello. Invece di creare semplici metodi passthrough nella logica business, si è preferito fondere i due livelli. Nella Figura 1 è illustrata l’architettura adottata. Figura 1. Commerce Starter Kit Database In questa sezione verrà descritto il database di Commerce Starter Kit. Si inizierà fornendo alcune informazioni su come sia stato progettato il database. Si proseguirà quindi con una descrizione dell’implementazione, comprensiva dell’illustrazione dettagliata dello schema del database e delle stored procedure. Creazione del modello dei dati Quando si crea un’applicazione, è sempre meglio partire dai dati. In altre parole, quando si inizia a progettare l’applicazione, è importante dapprima identificare le varie tabelle e i campi di cui si ha bisogno e che lastricheranno il percorso di progettazione e di realizzazione dell’intero costrutto. Come esempio, in Commerce Starter Kit sono state identificate 7 tabelle, descritte in dettaglio nella sezione seguente. Di queste tabelle, 6 sono state traslate direttamente in 6 classi corrispondenti. Anche di questo si parlerà diffusamente nella sezione che segue. Schema del database Nell’ottica della progettazione dello schema del database, è necessario dapprima esaminare i requisiti dell’applicazione. In questo caso, occorre un catalogo dei prodotti che i clienti possano consultare e da cui possano aggiungere articoli al loro carrello degli acquisti. Inoltre devono poter aggiungere commenti ai prodotti in modo che altri clienti possano prenderne visione. L’intenzione è di realizzare anche alcune funzionalità incrociate sulle vendite, come ad esempio un elenco del tipo “I clienti che hanno acquistato questo prodotto hanno anche acquistato...”. Nel sistema deve essere implementata anche una classifica del tipo “I prodotti più venduti...”. Considerando pertanto questi requisiti di alto livello,si è in grado di identificare rapidamente e con facilità le tabelle e le stored procedure del database, individuando semplicemente verbi e sostantivi in alcuni essenziali casi d’uso: 1. I Clienti (Customers) possono aggiungere (add) un determinato prodotto (product) al carrello della spesa (shopping cart). 2. I Clienti (Customers) possono aggiungere (add) un commento su un prodotto (product). 3. I Clienti (Customers) possono visionare (view) i prodotti per categoria (category). 4. I Clienti (Customers) possono verificare (checkout) il carrello della spesa (shopping cart) per inoltrare un ordine (order). Da questi casi d’uso si possono individuare numerosi oggetti, che sono sostantivi delle frasi stilate. Customers (Clienti) Products (Prodotti) Shopping Cart (Carrello della spesa) Reviews (Commenti) Categories (Categorie) Orders (Ordini) Considerando questi oggetti si riesce facilmente a individuare le principali tabelle del database. Lo schema fisico è illustrato nella Figura 2. Figura 2. Schema fisico del database Stored procedure In Commerce Starter Kit le stored procedure vengono utilizzate per incapsulare tutte le interrogazioni (query) al database. L’utilizzo di stored procedure determina una netta separazione tra il database e il livello intermedio di accesso ai dati. Questa condizione comporta una più facile manutenzione, in quanto eventuali modifiche al database saranno invisibili ai componenti di accesso ai dati. Sussistono inoltre ulteriori benefici in termini di prestazione in quanto le stored procedure sono ottimizzate la prima volta che vengono eseguite e successivamente conservate in memoria per le chiamate successive. Un buon esempio di una delle più complesse stored procedure di Commerce Starter Kit è quella denominata “ShoppingCartAddItem”. Con questa procedura si aggiunge un prodotto al carrello della spesa dell’utente. ShoppingCartAddItem CREATE Procedure ShoppingCartAddItem ( @CartID nvarchar(50), @ProductID int, @Quantity int ) As Declare @CountItems int SELECT @CountItems= Count(ProductID) FROM ShoppingCart WHERE ProductID= @ProductID AND CartID= @CartID IF @CountItems > 0 /* There are items - update the current quantity */ UPDATE ShoppingCart SET Quantity= (@Quantity + ShoppingCart.Quantity) WHERE ProductID= @ProductID AND CartID= @CartID ELSE /* New entry for this Cart. Add a new record */ INSERT INTO ShoppingCart (CartID, Quantity, ProductID) VALUES (@CartID, @Quantity, @ProductID) GO Livello di accesso al Database Commerce Starter Kit si avvale di un componente intermedio per fornire la comunicazione tra i Web form ASP.NET e il database SQL Server. In questa sezione verranno descritte le implementazioni di questo componente di accesso ai dati. Spazio dei nomi di ASP.NET Commerce Starter Kit Nella sezione “Creazione del modello dei dati”, si è evidenziata l’importanza di realizzare l’applicazione a partire dai dati. L’implementazione del componente di accesso ai dati ne è la conseguenza diretta, considerando un’ottica dell’applicazione incentrata sui dati e creando innanzitutto lo schema del database. Il componente in esame conterrà le seguenti classi, che sono associate alle tabelle del database. CustomersDB ProductsDB ShoppingCartDB ReviewsDB OrdersDB In Microsoft .NET, si possono raggruppare le classi in uno spazio dei nomi in grado di dare un’organizzazione al componente. In Commerce Starter Kit è stato creato uno spazio dei nomi chiamato ASPNET.StarterKit.Commerce, che conterrà tutte le classi indicate in precedenza. Lo spazio dei nomi è definito come “ASPNET.StarterKit.Commerce” e presenta la struttura illustrata nella Figura 3: Figura 3. Spazio dei nomi ASPNET.StarterKit.Commerce Gli spazi dei nomi non devono essere necessariamente contenuti in un unico file. In Commerce Starter Kit è stato creato un file di origine per ciascuna classe (con l’eccezione di OrderDetails e Orders) e tutti i file di origine sono stati compilati in un assembly, ASPNETCommerce.dll. Impostazione della sezione appSettings Prima di procedere con l’accesso ai dati, vi sono alcune operazioni propedeutiche da compiere. Per poter stabilire una connessione a SQL Server, il componente di livello intermedio esige le necessarie informazioni di connessione al database. Per fornirle si ricorre a una stringa di connessione, da trasmettere all’oggetto connessione per ogni query verso il database. Un’opzione potrebbe essere quella di definire una costante che contenga la stringa di connessione e di inserire tale costante nel componente. Tuttavia questa è una pratica da evitare, in quanto se si modifica la stringa di connessione (ad esempio, variando il percorso, la password e così via) si è costretti a ricompilare il componente, con non poche ripercussioni. Per evitare inutili ricompilazioni, la stringa di connessione può essere inserita nella sezione appSettings del file di configurazione dell’applicazione Web, web.config (situato nella cartella principale della directory virtuale dell’applicazione). <configuration> <appSettings> <add key="ConnectionString" value="server=localhost;uid=sa;pwd=;database=store" /> </appSettings> </configuration> A queste informazioni di configurazione si può accedere dal livello di accesso al database utilizzando la classe ConfigurationSettings nello spazio dei nomi System.Configurations. m_ConnectionString = (String) ConfigurationSettings.AppSettings["ConnectionString"]; Quest’istruzione è collocata in una proprietà public statica del livello di accesso ai dati, così da poter recuperare la stringa di connessione in qualsiasi punto del componente usando la seguente istruzione: ASPNET.StarterKit.Commerce.ConnectionString Oltre ai vantaggi dal punto di vista della manutenzione, ovvero la memorizzazione della stringa di connessione nel file web.config, le prestazioni dell’applicazione non risultano compromesse poiché la stringa viene inserita nella cache e verrà recuperata dal file web.config solo in seguito a eventuali modifiche. Modello comune Commerce Starter Kit si avvale del nuovo provider gestito per SQL Server, per ottenere le migliori prestazioni. La maggioranza dei metodi nel componente di accesso ai dati segue un modello molto simile che rispecchia la logica seguente: 1. Creazione di una connessione al database 2. Creazione di un oggetto Command 3. Impostazione del tipo di comando su Stored Procedure 4. Creazione e compilazione dei parametri 5. Esecuzione del comando 6. Chiusura della connessione Un valido esempio di quanto illustrato è il metodo GetProducts() nella classe ProductsDB: Metodo GetProducts public SqlDataReader GetProducts(int categoryID) { // Create Instance of Connection and Command Object SqlConnection myConnection = new SqlConnection(ASPNETCommerceDB.ConnectionString); SqlCommand myCommand = new SqlCommand("ProductsByCategory", myConnection); // Mark the Command as a stored procedure myCommand.CommandType = CommandType.StoredProcedure; // Add Parameters to the stored procedure SqlParameter parameterCategoryID = new SqlParameter("@CategoryID", SqlDbType.Int, 4); parameterCategoryID.Value = categoryID; myCommand.Parameters.Add(parameterCategoryID); // Execute the command myConnection.Open(); SqlDataReader result = myCommand.ExecuteReader(CommandBehavior.CloseConnection); // Return the datareader result return result; } Una caratteristica molto importante da osservare è la capacità intrinseca del metodo ExecuteReader del DataReader di chiudere la connessione quando è conclusa la lettura dei dati. In questo modo è più semplice aprire e leggere dati senza doversi preoccupare di chiudere la connessione. Come illustrato nel metodo GetProducts(), questa funzionalità si ottiene passando CommandBehavior.CloseConnection come argomento al metodo ExecuteReader. Confronto tra DataReader e DataSet Una delle questioni più ricorrenti in relazione all’accesso ai dati riguarda la differenza tra DataReader e DataSet. Quando conviene utilizzare un DataReader e quando invece un DataSet? Il DataReader è un lettore connesso, che fornisce una visibilità dei dati di tipo forward-only. In virtù di questa caratteristica, i DataReader sono molto rapidi in lettura e possono essere utilizzati nella maggior parte dei casi. Essendo tuttavia di tipo connesso e forward-only, vanno annoverate numerose limitazioni. Se si devono supportare funzionalità come l’impaginazione e l’ordinamento, ad esempio, non sarà possibile utilizzare un DataReader senza scrivere codice aggiuntivo. Se si vuole ricorrere all’API Cache di ASP.NET per memorizzare un particolare gruppo di risultati da utilizzare in più pagine, non si potrà usare un DataReader. In questi casi è necessario utilizzare il DataSet. Se inoltre si devono passare dati all’interno del livello del componente o se fosse necessario modificare i dati prima di utilizzarli, occorre usare, anche in questo caso, il DataSet. In Commerce Starter Kit il DataReader viene utilizzato in modo alquanto esclusivo, poiché, come accade in molte applicazioni Web, la maggior parte dei dati è in sola lettura e l’interesse prevalente è quello dell’accesso più rapido possibile ai dati. Questa è la soluzione più vicina all’ideale per la maggior parte degli scenari, con l’eccezione dei casi in cui servono funzionalità al di là di un lettore forward-only. Compilazione del componente La compilazione del componente di livello intermedio dipenderà da quale versione dell’applicazione si sta utilizzando (Visual Studio.NET oppure SDK). In entrambi i casi, il processo di compilazione è molto semplice ed è stato automatizzato. Visual Studio.NET All’interno dell’IDE di Visual Studio.NET, per ricompilare il componente di livello intermedio è sufficiente aprire il menu Generazione e selezionare Rigenera. .NET Framework SDK Commerce Starter Kit è distribuito con un file batch che può essere utilizzato per ricompilare il componente di livello intermedio quando si esegue l’applicazione senza aver installato Visual Studio .NET. Questo file batch è denominato mk.bat e si trova nella cartella Components. Se si modifica uno qualsiasi dei file di origine del componente, è necessario ricompilarli per aggiornare la libreria Store.dll. Si può anche compilare il componente senza avvalersi del file batch. In tal caso, si utilizza il compilatore da riga di comando di Visual Basic.NET (o l’equivalente C# se si sta implementando in tale linguaggio). Il compilatore da riga di comando di Visual Basic.NET è un file denominato vbc.exe. Per ottenere un elenco di tutte le opzioni di compilazione, digitare vbc al prompt dei comandi. Nella Tabella 1 sono riepilogate le opzioni di compilazione principali necessarie per i componenti in esame. Opzione del compilatore Descrizione /out:<file> Specifica il nome del file di output /target:<tipo> Specifica il tipo di destinazione (forma abbreviata: /t) library (assembly di librerie, dll) exe (applicazione console) winexe (applicazione Windows) module (modulo da aggiungere a un assembly) /reference:<elenco_file> Crea un riferimento ai metadati dall’assembly specificato (forma abbreviata: /r) Tabella 1. Parametri del compilatore da riga di comando Un esempio comune di formato per compilare un assembly di librerie, che è quanto si sta realizzando nel Commerce Starter Kit, potrebbe essere il seguente: vbc /out:..\bin\MyLibrary.dll /t:library /r:System.Data.dll Source.cs Con questo esempio verrebbe compilato il codice sorgente contenuto nel file Source.cs, creato un riferimento allo spazio dei nomi System.Data e generata la libreria denominata MyLibrary.dll nella cartella bin secondo il percorso indicato. Progettazione dell’applicazione Web Il livello di presentazione di Commerce Starter Kit è stato realizzato utilizzando Web Form ASP.NET. In questa sezione verrà descritto come è stato utilizzato ASP.NET per implementare numerose funzionalità chiave di Commerce Starter Kit. La pagina di accesso (Login) Un compito essenziale tipico della maggior parte delle applicazioni Web è l’autenticazione degli utenti. ASP.NET offre una varietà di schemi di sistemi di autenticazione predefiniti. In Commerce Starter Kit viene utilizzato lo schema FormsAuthentication (descritto dettagliatamente nella sezione “Protezione e distribuzione”), delineato nel seguente codice sorgente della pagina Login.aspx. // Save old ShoppingCartID ASPNET.StarterKit.Commerce.ShoppingCartDB shoppingCart = new ASPNET.StarterKit.ShoppingCartDB(); String tempCartID = shoppingCart.GetShoppingCartId(); // Attempt to Validate User Credentials using CustomersDB ASPNET.StarterKit.CustomersDB accountSystem = new ASPNET.StarterKit.CustomersDB(); String customerId = accountSystem.Login(email.Text, password.Text); if (customerId != null) { // Migrate any existing shopping cart items into the // permanent shopping cart shoppingCart.MigrateCart(tempCartID, customerId); // Lookup the customer's full account details ASPNETCommerce.CustomerDetails customerDetails = accountSystem.GetCustomerDetails(customerId); // Store the user's fullname in a cookie for personalization purposes Response.Cookies["ASPNETCommerce_FullName"].Value = customerDetails.FullName; // Make the cookie persistent only if the user selects // "persistent" login checkbox if (RememberLogin.Checked == true) { Response.Cookies["ASPNETCommerce_FullName"].Expires = DateTime.Now.AddMonths(1); } // Redirect browser back to originating page FormsAuthentication.RedirectFromLoginPage(customerId, RememberLogin.Checked); } else { Message.Text = "Accesso non riuscito"; } Il primo passo del processo di registrazione e accesso consiste nel salvare l’attuale ID del carrello della spesa, in modo tale che il contenuto del carrello possa essere trasferito nel carrello permanente dell’utente corrente. Una volta completato questo primo passo, le informazioni di accesso dell’utente vengono convalidate in base al database. Se la convalida ha esito positivo, vengono recuperate le informazioni complete dell’utente e il nome completo viene memorizzato in un cookie per scopi di personalizzazione. Una data di scadenza viene predisposta per il cookie se l’utente ha specificato di “ricordare le informazioni di accesso”, altrimenti il cookie sarà distrutto alla fine della sessione. Dopo questi passi viene effettuata la chiamata al metodo RedirectFromLoginPage, con il quale viene inviato un ticket di autenticazione al client e reindirizzato l’utente verso la pagina cui stava tentando di accedere. Elenco dei prodotti (Product Listing) I controlli server ASP.NET sono un insieme di controlli dalle molteplici funzionalità che hanno lo scopo di incrementare l’incapsulamento del codice e aumentare la produttività. Esistono tre tipi di controlli server: controlli HTML, controlli Forms e controlli Bound List. Dichiarare un controllo server è semplice, come si può vedere di seguito: <asp:Label id="MyLabel" class="MyLabelText" runat="server" /> L’attributo “id” identifica il controllo server, mentre l’attributo “runat” indica che si tratta proprio di un controllo server. I controlli HTML vengono utilizzati per form che sono già sviluppati usando elementi HTML esistenti, mentre i controlli Forms e List vengono usati per nuovi web form. L’immagine relativa all’elenco di prodotti è un ottimo esempio di utilizzo di controlli Bound List. La pagina contiene un controllo DataList, che permette agli sviluppatori di visualizzare facilmente contenuti di un’origine dati, in questo caso informazioni sui prodotti. Il DataList contiene numerosi template che possono essere impostati e che consentono agli sviluppatori di gestire il modo in cui i dati sono rappresentati nel controllo. Oltre alla semplice rappresentazione dell’origine dati, il controllo DataList offre numerose ricche funzionalità che permettono l’accrescimento della produttività. Nel caso dell’immagine relativa all’elenco di prodotti, l’intenzione è stata quella di visualizzare due colonne di prodotti. Questo risultato si ottiene impostando una proprietà del DataList, denominata RepeatColumns. In questo caso si tratta di un esempio delle numerose funzionalità offerte dai controlli List di ASP.NET. Il codice del DataList in questione è rappresentato di seguito. <asp:DataList id="MyList" RepeatColumns="2" runat="server"> <ItemTemplate> <table border="0" width="300"> <tr> <td width="25"> &nbsp; </td> <td width="100" valign="middle" align="right"> <a href='ProductDetails.aspx?productID=<%# DataBinder.Eval(Container.DataItem, "ProductID") %>'> <img src='ProductImages/thumbs/<%# DataBinder.Eval(Container.DataItem, "ProductImage") %>' width="100" height="75" border="0"> </a> </td> <td width="200" valign="middle"> <a href='ProductDetails.aspx?productID=<%# DataBinder.Eval(Container.DataItem, "ProductID") %>'> <span class="ProductListHead"> <%# DataBinder.Eval(Container.DataItem, "ModelName") %> </span> <br> </a><span class="ProductListItem"><b>Prezzo speciale: </b> <%# DataBinder.Eval(Container.DataItem, "UnitCost", "{0:c}") %> </span> <br> <a href='AddToCart.aspx?productID=<%# DataBinder.Eval(Container.DataItem, "ProductID") %>'> <span class="ProductListItem"><font color="#9D0000"> <b>Aggiungi al carrello<b></font></span> </a> </td> </tr> </table> </ItemTemplate> </asp:DataList> Il menu di ASP.NET Commerce Starter Kit I controlli utente sono oggetti Widget personalizzati della UI in cui sono incapsulate funzionalità. Possono essere utilizzati per incrementare la produttività grazie alla capacità di riutilizzo del codice. I controlli utente sono simili alle tradizionali istruzioni Includes lato server, con la differenza che sono molto più potenti e flessibili. Possono contenere proprietà e incapsulare logica che può essere esposta ai Web form che li includono. Questa condizione consente agli sviluppatori di creare controlli utente intelligenti che possono essere riutilizzati in numerose applicazioni, ma che contengono porzioni personalizzate per ciascuna applicazione. Commerce Starter Kit contiene numerosi controlli utente riutilizzati in vario modo nell’ambito dell’applicazione. Un esempio è il controllo utente menu. Tramite questo controllo viene visualizzato un elenco di collegamenti corrispondenti alle diverse categorie di prodotti. Per implementare il contenuto del menu si è scelto un DataList, in quanto consente di visualizzare l’elemento selezionato dall’utente in modo differenziato; in tal modo l’utente stesso è in grado di capire quale categoria sta esplorando. Un controllo utente viene aggiunto a un Web form aggiungendo una direttiva Register per il controllo medesimo. La direttiva contiene tre attributi: TagPrefix, che fornisce un unico spazio dei nomi per il controllo utente; TagName, che fornisce un nome univoco al controllo utente; infine, Src, che contiene il percorso virtuale per il controllo utente. La direttiva Register con cui aggiungere il controllo utente Menu è illustrata di seguito. <%@ Register TagPrefix="ASPNETCommerce" TagName="Menu" Src="_Menu.ascx" %> Una volta aggiunta la direttiva Register alla pagina, occorre definire la collocazione del controllo utente nella pagina stessa. È sufficiente aggiungere il tag del controllo utente alla UI del Web form. Il tag del controllo utente Menu è simile a quello illustrato di seguito: <ASPNETCommerce:Menu id="Menu1" runat="server" /> Carrello della spesa (Shopping Cart) Una delle caratteristiche significative del controllo DataGrid consiste nella capacità di effettuare modifiche inline. Questo risultato è possibile definendo una colonna come TemplateColumn e riempiendola con un altro controllo server ASP.NET, come una casella di testo (TextBox) o una casella di controllo (CheckBox). Un esempio di quanto descritto è illustrato nel carrello della spesa dI Commerce Starter Kit illustrato nella Figura 4. Figura 4. Carrello della spesa Per impostazione predefinita, nel DataGrid vengono aggiunte automaticamente colonne per ogni campo dell’origine dati. Le colonne nel DataGrid possono essere personalizzate impostando la proprietà AutoGenerateColumns su false e manipolando l’insieme Columns della griglia. L’implementazione del DataGrid del carrello della spesa dimostra quanto descritto: <asp:DataGrid id="MyList" runat="server" BorderColor="black" GridLines="Vertical" cellpadding="4" cellspacing="0" Font-Name="Verdana" Font-Size="8pt" ShowFooter="true" HeaderStyle-CssClass="CartListHead" FooterStyle-CssClass="CartListFooter" ItemStyle-CssClass="CartListItem" AlternatingItemStyle-CssClass="CartListItemAlt" DataKeyField="Quantity" AutoGenerateColumns="false"> <Columns> <asp:TemplateColumn HeaderText="Product&nbsp;ID"> <ItemTemplate> <asp:Label id="ProductID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "ProductID") %>' /> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn HeaderText="Product Name" DataField="ModelName" /> <asp:BoundColumn HeaderText="Model" DataField="ModelNumber" /> <asp:TemplateColumn HeaderText="Quantity"> <ItemTemplate> <asp:TextBox id="Quantity" runat="server" Columns="4" Text='<%# DataBinder.Eval(Container.DataItem, "Quantity") %>' width="40px" /> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn HeaderText="Price" DataField="UnitCost" DataFormatString="{0:c}" /> <asp:BoundColumn HeaderText="Subtotal" DataField="ExtendedAmount" DataFormatString="{0:c}" /> <asp:TemplateColumn HeaderText="Remove"> <ItemTemplate> <center> <asp:CheckBox id="Remove" runat="server" /> </center> </ItemTemplate> </asp:TemplateColumn> </Columns> </asp:DataGrid> Supporto per browser diversi Le applicazioni Web tipiche devono tenere in considerazione molti requisiti in merito al supporto da offrire ai diversi browser, quali Internet Explorer e Netscape, nonché alle versioni precedenti degli stessi o di altri tipi (è ad esempio molto frequente il caso di applicazioni sono tuttora utilizzate in Internet Explorer 4.0 o versioni precedenti). Mantenere un aspetto consistente in Internet Explorer così come in Netscape Navigator è essenziale per garantire univocità di esperienza e approccio tra i diversi browser. Ecco alcuni suggerimenti da considerare: 1. Utilizzare un file di stile CSS 2. Prestare attenzione all’ortografia del nome di classe CSS: questo aspetto è molto importante in Navigator 6 3. Nel caso degli input, aggiungere l’attributo Size per Navigator È anche importante effettuare un buon test delle pagine in fase di sviluppo su browser diversi. Prestazioni Si possono migliorare notevolmente le prestazioni della propria applicazione giovandosi delle capacità di caching di ASP.NET. In ASP.NET sono disponibili tre tipi di caching: il caching di output, il caching di frammenti e il caching di dati. Il primo tipo di caching permette al contenuto di una pagina (dopo essere stata sottoposta a parsing sul server e riprodotta come HTML) di essere memorizzato in una cache ed essere restituito alle richieste HTTP senza ulteriori trasformazioni per un certo periodo di tempo. La caching di frammenti consente di inserire in cache una specifica porzione di pagina per un determinato periodo di tempo. Infine, la caching dei dati fornisce un’API che consente accesso diretto alla cache. La caching dei frammenti è utilizzata dovunque nell’applicazione Commerce Starter Kit. Un esempio di questa caching è illustrato nel controllo utente Menu. All’inizio della pagina _menu.ascx, si può osservare la seguente direttiva, che abilita la caching dei frammenti per il controllo utente. <%@ OutputCache Duration="3600" VaryByParam="Selection" %> L’attributo Duration indica di inserire in cache il controllo utente _menu.ascx per 3600 secondi. VaryByParam permette di specificare diverse istanze del controllo nella cache. In questo modo si possono inserire in cache controlli utente che variano in funzione delle proprietà public. In questo caso, VaryByParam è impostato su “Selection”, vale a dire che più copie del controllo menu, ciascuna delle quali mostra una selezione diversa, saranno memorizzate nella cache. Protezione e distribuzione Commerce Starter Kit può contare su un processo di configurazione automatizzato che permette la distribuzione tanto su un singolo computer quanto su un intero centro di elaborazione dati. Sono numerose le considerazioni da tenere presente quando si distribuisce e si mette in sicurezza un’applicazione Web, con impatti sul lato operativo (ad esempio, rivalutare la destinazione d’uso ed effettuare modifiche alle configurazioni) e su quello applicativo (ad esempio, le prestazioni dell’applicazione). Autenticazione basata su form ASP.NET offre un sistema di autenticazione predefinito noto come autenticazione basata su form. Con questo sistema occorre specificare una pagina di accesso nella sezione di autenticazione del file web.config. Di seguito è illustrata la sezione di autenticazione di Commerce Starter Kit: <system.web> <authentication mode="Forms"> <forms name="ASPNETCommerceAuth" loginUrl="login.aspx" protection="All" path="/" /> </authentication> </system.web> Si deve poi aggiungere una sezione di collocazione (location) per ogni pagina in cui è richiesta autenticazione. Di seguito è illustrato un esempio per la pagina “Checkout.aspx”. <location path="Checkout.aspx"> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location> Il percorso (path) indica al sistema il file per il quale è richiesta l’autenticazione. La porzione <deny users=”?” /> indica che tutti gli utenti non autenticati non avranno accesso alla pagina. Quando un utente non autenticato tenta di aprire la pagina in questione, viene immediatamente reindirizzato alla pagina di registrazione e accesso, definita precedentemente. Quando l’utente fornisce adeguate credenziali, viene autenticato nella pagina di accesso e reindirizzato nuovamente alla pagina che tentava di aprire. FormsAuthentication.RedirectFromLoginPage(customerId, RememberLogin.Checked); Distribuzione Il processo di distribuzione aggiornato è una delle funzionalità più importanti tra quelle offerte da Microsoft .NET Framework. In passato, distribuire il livello di accesso al database e quello di presentazione, non era di per sé un grosso problema; per la distribuzione dei componenti, invece, era necessaria la registrazione sul server. Questa condizione determinava numerosi problemi che sembravano sempre insorgere inaspettatamente, come quello comunemente denominato “inferno delle DLL”, nel quale insorgevano problemi con altre applicazioni e componenti a causa di versioni diverse del componente. Microsoft .NET ha risolto questo problema eliminando complessivamente il bisogno di registrazione. I componenti, più correttamente definiti assembly, sono ora autodescrittivi; viene così eliminata la necessità di memorizzarne le informazioni nel Registro del sistema. In altre parole, quando si installa un’applicazione .NET, ci si limita a copiare i componenti nella cartella “bin” dell’applicazione stessa. I metadati disponibili nell’assembly forniscono infatti tutte le informazioni necessarie all’applicazione per collocare e utilizzare i componenti. Web Farm Nella maggioranza dei casi, Commerce Starter Kit supporta il Web farming “così com’è”. In altre parole, è possibile installare l’applicazione su più server permettendo così al cluster di distribuire il carico tra i diversi server. L’unico requisito di configurazione è l’autenticazione. Quando si accede alla vetrina, l’autenticazione di ASP.NET crea un cookie per il browser, impostato e letto dal server. Una volta autenticati, se si passa a una pagina che richiede autenticazione, il server cerca il cookie e, se lo trova, consente l’accesso alla pagina protetta. Considerando uno scenario di tipo Web farm, gli utenti possono autenticarsi con un server (vale a dire che un cookie è generato per quel server), ma poi possono richiedere una pagina che necessita di autenticazione con un altro server della farm (privo di cookie). In base alle impostazioni di affinità della sessione della soluzione di bilanciamento del carico, può verificarsi la necessità di autenticarsi ogni volta che si accede a un nuovo server Web. Per evitare questo intoppo, occorre semplicemente apportare una modifica al Commerce Starter Kit in modo da condividere il cookie su tutti i server (oppure attivare l’affinità di sessione). Per impostazione predefinita, la chiave di decrittografia del cookie di autenticazione è impostata su “autogenerate”, ovvero tale chiave è impostata in modo casuale in funzione del server. In pratica, i server non sono in grado di utilizzare cookie di altri server. Questo problema può essere risolto manualmente impostando la chiave di decrittografia in modo da renderla unica per tutti i server della Web farm. L’impostazione della chiave si effettua con il seguente elemento del file web.config. <machineKey decryptionKey="213454ABE333321D" /> La chiave di decrittografia è stata selezionata in modo casuale; occorre semplicemente che sia la stessa per tutti i file web.config dei diversi server. Il livello di protezione predefinito per l’autenticazione basata su form è stato inoltre modificato da “All” a “None”. <authentication mode="Forms"> <forms name="ASPNETCommerceAuth" loginUrl="login.aspx" protection="None" /> </authentication> Conclusioni Lo sviluppo di applicazioni Web distribuite è stato notevolmente semplificato dalle tecnologie di Microsoft .NET. I Web Form ASP.NET, le capacità di caching e la semplicità dell’accesso ai dati in .NET migliorano complessivamente il processo di sviluppo di applicazioni, dalla rilevazione dei requisiti alla distribuzione e manutenzione. Per illustrare inoltre le tecnologie fondamentali nuove in .NET, l’applicazione Commerce Starter Kit serve a fornire un modello per la realizzazione di applicazioni e-commerce online. Per maggiori informazioni La documentazione completa e il codice sorgente sono disponibili nel sito Web all’indirizzo http://www.asp.net Per una versione dal vivo del sito, visitare il sito Web all’indirizzo http://www.asp.net IBuySpy Listserver http://www.aspfriends.com/aspfriends/aspngibuyspy.asp Per un elenco completo delle risorse di ASP.NET, visitare il sito Web all’indirizzo http://www.asp.net