3. Introduzione allo sviluppo web con ASP.NET
3.1. Introduzione
Il capitolo precedente ha introdotto i principi dello sviluppo web, che sono indipendenti dal linguaggio di programmazione utilizzato. Attualmente, tre tecnologie dominano il mercato dello sviluppo web:
- J2EE, che è una piattaforma di sviluppo Java. In combinazione con la tecnologia Struts, installata su vari server applicativi, la piattaforma J2EE viene utilizzata principalmente in progetti su larga scala. Grazie al linguaggio utilizzato, Java, un'applicazione J2EE può essere eseguita sui principali sistemi operativi (Windows, Unix, Linux, Mac OS, ecc.)
- PHP, che è un linguaggio interpretato anch'esso indipendente dal sistema operativo. A differenza di Java, non è un linguaggio orientato agli oggetti. Tuttavia, si prevede che la versione PHP5 introdurrà funzionalità orientate agli oggetti nel linguaggio. Facile da usare, PHP è ampiamente utilizzato in progetti di piccole e medie dimensioni.
- ASP.NET è una tecnologia che funziona solo su macchine Windows dotate della piattaforma .NET (XP, 2000, 2003, ecc.). Il linguaggio di sviluppo utilizzato può essere qualsiasi linguaggio compatibile con .NET, ovvero più di una dozzina, a partire dai linguaggi Microsoft (C#, VB.NET, J#), Delphi di Borland, Perl, Python, ...
Il capitolo precedente ha presentato brevi esempi per ciascuna di queste tre tecnologie. Il presente documento si concentra sullo sviluppo web ASP.NET utilizzando il linguaggio VB.NET. Si presume che l'utente abbia familiarità con questo linguaggio. Questo punto è importante. Qui ci occupiamo esclusivamente del suo utilizzo nel contesto dello sviluppo web. Approfondiamo questo punto discutendo la metodologia MVC per lo sviluppo web.
Un'applicazione web che segue il modello MVC sarà strutturata come segue:

Tale architettura, nota come architettura a 3 livelli, mira ad aderire al modello MVC (Model-View-Controller):
- l'interfaccia utente è la V (la vista)
- la logica dell'applicazione è il C (il controller)
- le fonti di dati sono la M (Model)
L'interfaccia utente è spesso un browser web, ma potrebbe anche essere un'applicazione autonoma che invia richieste HTTP al servizio web attraverso la rete e formatta i risultati ricevuti. La logica dell'applicazione consiste in script che elaborano le richieste degli utenti. La fonte di dati è spesso un database, ma può anche trattarsi di semplici file flat, una directory LDAP, un servizio web remoto, ecc. È nell'interesse dello sviluppatore mantenere un alto grado di indipendenza tra queste tre entità, in modo che se una di esse cambia, le altre due non debbano cambiare, o solo in misura minima.
- La logica di business dell'applicazione sarà collocata in classi separate dalla classe che controlla il dialogo richiesta-risposta. Pertanto, il blocco [Logica dell'applicazione] sopra riportato potrebbe essere costituito dai seguenti elementi:

All'interno del blocco [Logica dell'applicazione], possiamo distinguere
- la classe controller, che funge da punto di ingresso dell'applicazione.
- il blocco [Classi di business], che raggruppa le classi necessarie per la logica dell’applicazione. Queste sono indipendenti dal client.
- il blocco [Classi di accesso ai dati], che raggruppa le classi necessarie per recuperare i dati richiesti dal servlet, spesso dati persistenti (database, file, servizi web, ecc.)
- il blocco di pagine ASP che costituiscono le viste dell’applicazione.
In casi semplici, la logica dell'applicazione si riduce spesso a due classi:
- la classe controller che gestisce la comunicazione client-server: elaborazione della richiesta e generazione di varie risposte
- la classe business che riceve i dati da elaborare dal controller e gli restituisce i risultati. Questa classe business gestisce poi l'accesso ai dati persistenti.
L'aspetto unico dello sviluppo web risiede nella scrittura della classe controller e delle pagine di presentazione. Le classi business e di accesso ai dati sono classi .NET standard che possono essere utilizzate in un'applicazione web così come in un'applicazione Windows o persino in un'applicazione console. La scrittura di queste classi richiede una solida comprensione della programmazione orientata agli oggetti. In questo documento, saranno scritte in VB.NET, quindi diamo per scontato che tu abbia una buona padronanza di questo linguaggio. Da questo punto di vista, non è necessario soffermarsi sul codice di accesso ai dati più del necessario. In quasi tutti i libri su ASP.NET, un capitolo è dedicato ad ADO.NET. Il diagramma sopra mostra che l'accesso ai dati è gestito da classi .NET standard che non sono consapevoli di essere utilizzate in un contesto web. Il controller, che funge da caposquadra dell'applicazione web, non deve preoccuparsi di ADO.NET. Deve semplicemente sapere a quale classe richiedere i dati necessari e come richiederli. Tutto qui. Inserire il codice ADO.NET nel controller viola il concetto MVC spiegato sopra, e non lo faremo.
3.2. Strumenti
Questo documento è destinato agli studenti, quindi lavoreremo con strumenti gratuiti disponibili per il download su Internet:
- la piattaforma .NET (compilatori, documentazione)
- l'ambiente di sviluppo WebMatrix, che include il server web Cassini
- vari DBMS (MSDE, MySQL)
Si consiglia ai lettori di consultare l'appendice "Strumenti Web", che spiega dove trovare e come installare questi vari strumenti. Il più delle volte, avremo bisogno solo di tre strumenti:
- un editor di testo per scrivere applicazioni web.
- uno strumento di sviluppo VB.NET per scrivere codice VB quando è necessario. Questo tipo di strumento offre generalmente assistenza nell'inserimento del codice (completamento automatico) e il rilevamento degli errori di sintassi, sia durante la digitazione del codice che durante la compilazione.
- un server web per testare le applicazioni web che avete scritto. In questo documento useremo Cassini. I lettori che dispongono di un server IIS possono sostituire Cassini con IIS. Entrambi sono compatibili con .NET. Tuttavia, Cassini è limitato a rispondere solo alle richieste locali (localhost), mentre IIS può rispondere alle richieste provenienti da macchine esterne.
Un eccellente ambiente commerciale per lo sviluppo in VB.NET è Visual Studio.NET di Microsoft. Questo IDE ricco di funzionalità consente di gestire tutti i tipi di documenti (codice VB.NET, documenti HTML, XML, fogli di stile, ecc.). Per la scrittura del codice, fornisce l'inestimabile assistenza del "completamento" automatico del codice. Detto questo, questo strumento, che migliora significativamente la produttività dello sviluppatore, presenta un lato negativo: limita lo sviluppatore a una modalità di sviluppo standard che è certamente efficiente ma non sempre appropriata.
È possibile utilizzare il server Cassini al di fuori di [WebMatrix], ed è proprio ciò che faremo spesso. L'eseguibile del server si trova in <WebMatrix>\<versione>\WebServer.exe, dove <WebMatrix> è la directory di installazione di [WebMatrix] e <versione> è il numero di versione:

Apriamo una finestra del Prompt dei comandi e navighiamo fino alla cartella del server Cassini:
E:\Program Files\Microsoft ASP.NET Web Matrix\v0.6.812>dir
...
29/05/2003 11:00 53 248 WebServer.exe
...
Eseguiamo [WebServer.exe] senza alcun parametro:

Il pannello sopra mostra che l'applicazione [WebServer/Cassini] accetta tre parametri:
- /port: numero di porta del servizio web. Può essere qualsiasi numero. Il valore predefinito è 80
- /path: percorso fisico di una cartella sul disco
- /vpath: cartella virtuale associata alla cartella fisica precedente.
Inseriremo i nostri esempi in una struttura di file con la directory principale P e le cartelle chap1, chap2, ... corrispondenti ai diversi capitoli di questo documento. Assoceremo il percorso virtuale V a questa cartella fisica P. Avvieremo inoltre Cassini con il seguente comando DOS:
Ad esempio, se vogliamo che la radice fisica del server sia la cartella [D:\data\devel\aspnet\poly] e la sua radice virtuale sia [aspnet], il comando DOS per avviare il server web sarà:
È possibile salvare questo comando come collegamento. Una volta avviato, Cassini inserisce un'icona nella barra delle applicazioni. Facendo doppio clic su di essa si apre un pannello di avvio/arresto del server:

Il pannello mostra i tre parametri utilizzati per avviarlo. Offre due pulsanti di avvio/arresto e un link di prova alla radice della sua struttura di directory web. Facciamo clic su di esso. Si apre un browser e viene richiesto l'URL [http://localhost/aspnet]. Vediamo il contenuto della cartella specificata nel campo [Percorso fisico] sopra:

In questo esempio, l'URL richiesto corrisponde a una cartella piuttosto che a un documento web, quindi il server ha visualizzato il contenuto di quella cartella anziché un documento web specifico. Se in questa cartella è presente un file denominato [default.aspx], verrà visualizzato. Ad esempio, creiamo il seguente file e inseriamolo nella radice dell'albero web di Cassini (qui d:\data\devel\aspnet\poly):
Ora proviamo a richiedere l'URL [http://localhost/aspnet] utilizzando un browser:

Notiamo che in realtà è stato visualizzato l'URL [http://localhost/aspnet/default.aspx]. Più avanti in questo documento spiegheremo come configurare Cassini utilizzando la notazione Cassini(path,vpath), dove [path] è il nome della cartella radice dell'albero delle directory web del server e [vpath] è il percorso virtuale associato. Ricordiamo che con il server Cassini(path,vpath), l'URL [http://localhost/vpath/XX] corrisponde al percorso fisico [path\XX]. Collocheremo tutti i nostri documenti in una directory radice fisica che chiameremo <webroot>. Pertanto, possiamo fare riferimento al file <webroot>\chap2\here1.aspx. Per ogni lettore, questa directory <webroot> sarà una cartella sul proprio computer personale. Qui, le schermate mostreranno che questa cartella è spesso [d:\data\devel\aspnet\poly]. Tuttavia, non sarà sempre così, poiché i test sono stati eseguiti su macchine diverse.
3.3. Primi esempi
Presenteremo alcuni semplici esempi di pagine web dinamiche create con VB.NET. Invitiamo i lettori a provarle per verificare che il loro ambiente di sviluppo sia installato correttamente. Vedremo che ci sono diversi modi per creare una pagina ASP.NET. Ne sceglieremo uno per il resto del nostro lavoro di sviluppo.
3.3.1. Esempio di base - Variante 1
Strumenti necessari: un editor di testo, il server web Cassini
Riprenderemo l'esempio del capitolo precedente. Creeremo il seguente file [heure1.aspx]:
<html>
<head>
<title>Demo asp.net </title>
</head>
<body>
Il est <% =Date.Now.ToString("T") %>
</body>
</html>
Questo codice è codice HTML con uno speciale tag <% ... %>. All'interno di questo tag è possibile inserire codice VB.NET. In questo caso, il codice
genera una stringa C che rappresenta l'ora corrente. Il tag <% ... %> viene quindi sostituito da questa stringa C. Quindi, se C è la stringa 18:11:01, la riga HTML contenente il codice VB.NET diventa:
Inseriamo il codice precedente nel file [<webroot>\chap2\heure1.aspx]. Avviamo Cassini(<webroot>,/aspnet) e richiediamo l'URL [http://localhost/aspnet/chap2/heure1.aspx] in un browser:

Una volta ottenuto questo risultato, sappiamo che l'ambiente di sviluppo è installato correttamente. La pagina [heure1.aspx] è stata compilata poiché contiene codice VB.NET. La sua compilazione ha prodotto un file DLL che è stato memorizzato in una cartella di sistema e quindi eseguito dal server Cassini.
3.3.2. Esempio di base - variante 2
Strumenti necessari: un editor di testo, il server web Cassini
Il documento [heure1.aspx] mescola codice HTML e codice VB.NET. In un esempio così semplice, questo non è un problema. Se è necessario includere più codice VB.NET, è consigliabile separare più chiaramente il codice HTML dal codice VB. Ciò può essere fatto racchiudendo il codice VB all'interno di un tag <script>:
<script runat="server">
' calcul des données à afficher par le code HTML
...
</script>
<html>
....
' affichage des valeurs calculées par la partie script
</html>
L'esempio [heure2.aspx] illustra questo metodo:
<script runat="server">
Dim maintenant as String=Date.Now.ToString("T")
</script>
<html>
<head>
<title>Demo asp.net </title>
</head>
<body>
Il est
<% =maintenant %>
</body>
</html>
Inseriamo il documento [heure2.aspx] nella struttura di directory [<webroot>\chap2\heure2.aspx] sul server web Cassini (<webroot>,/aspnet) e richiediamo il documento utilizzando un browser:

3.3.3. Esempio di base - Variante 3
Strumenti necessari: un editor di testo, il server web Cassini
Portiamo la separazione tra codice VB e codice HTML un passo avanti, inserendoli in due file distinti. Il codice HTML sarà nel file [heure3.aspx] e il codice VB in [heure3.aspx.vb]. Il contenuto di [heure3.aspx] sarà il seguente:
<%@ Page Language="vb" src="heure3.aspx.vb" Inherits="heure3" %>
<html>
<head>
<title>Demo asp.net</title>
</head>
<body>
Il est
<% =maintenant %>
</body>
</html>
Ci sono due differenze fondamentali:
- la direttiva [Page] con attributi non ancora definiti
- l'uso della variabile [now] nel codice HTML anche se non è inizializzata da nessuna parte
La direttiva [Page] viene utilizzata qui per indicare che il codice VB che inizializzerà la pagina si trova in un altro file. L'attributo [src] specifica questo file. Vedremo che il codice VB appartiene a una classe chiamata [heure3]. In modo trasparente per lo sviluppatore, un file .aspx viene convertito in una classe che deriva da una classe base chiamata [Page]. In questo caso, il nostro documento HTML deve derivare dalla classe che definisce e calcola i dati che deve visualizzare. In questo caso, si tratta della classe [heure3] definita nel file [heure3.aspx.vb]. Dobbiamo quindi specificare questa relazione padre-figlio tra il documento VB [heure3.aspx.vb] e il documento HTML [heure3.aspx]. L'attributo [inherits] specifica questa relazione. Deve indicare il nome della classe definita nel file indicato dall'attributo [src].
Esaminiamo ora il codice VB della pagina:
Public Class heure3
Inherits System.Web.UI.Page
' data of the web page to be displayed
Protected maintenant As String
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'calculates the web page data
maintenant = Date.Now.ToString("T")
End Sub
End Class
Si notino i seguenti punti:
- Il codice VB definisce una classe [heure3] derivata dalla classe [System.Web.UI.Page]. È sempre così, poiché una pagina web deve sempre derivare da [System.Web.UI.Page].
- La classe dichiara un attributo protetto [now]. Sappiamo che un attributo protetto è direttamente accessibile nelle classi derivate. Questo è ciò che permette al documento HTML [heure3.aspx] di accedere al valore dei dati [now] nel suo codice.
- L'attributo [maintenant] viene inizializzato in una procedura [Page_Load]. Vedremo in seguito che un oggetto [Page] riceve dal server web la notifica di una serie di eventi. L'evento [Load] si verifica quando l'oggetto [Page] e i suoi componenti sono stati creati. Il gestore di questo evento è designato dalla direttiva [Handles MyBase.Load]
- Il nome [XX] del gestore di eventi può essere qualsiasi cosa. La sua firma deve essere quella mostrata sopra. Per ora non lo spiegheremo in dettaglio.
- Spesso utilizziamo il gestore di eventi [Page.Load] per calcolare i valori dei dati dinamici che la pagina web deve visualizzare.
I file [heure3.spx] e [heure3.aspx.vb] si trovano in [<webroot>\chap2]. Quindi, utilizzando un browser, richiediamo l'URL [http://localhost/aspnet/chap2/heure3.aspx] dal server web (<webroot>,/aspnet):

3.3.4. Esempio di base - Variante 4
Strumenti necessari: un editor di testo, il server web Cassini
Utilizziamo lo stesso esempio di prima, ma consolidiamo tutto il codice in un unico file [heure4.aspx]:
<script runat="server">
' data of the web page to be displayed
Private maintenant As String
' evt page_load
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'calculates the web page data
maintenant = Date.Now.ToString("T")
End Sub
</script>
<html>
<head>
<title>Demo asp.net</title>
</head>
<body>
Il est
<% =maintenant %>
</body>
</html>
Vediamo la stessa sequenza dell'Esempio 2:
In questo caso, il codice VB è stato organizzato in procedure. Si nota la procedura [Page_Load] dell'esempio precedente. L'obiettivo è dimostrare che una pagina .aspx autonoma (non collegata al codice VB in un file separato) viene implicitamente convertita in una classe derivata da [Page]. Pertanto, possiamo utilizzare gli attributi, i metodi e gli eventi di questa classe. Questo è ciò che viene fatto qui, dove utilizziamo l'evento [Load] di questa classe.
Il metodo di test è identico a quelli precedenti:

3.3.5. Esempio di base - Variante 5
Strumenti necessari: un editor di testo, il server web Cassini
Come nell'Esempio 3, separiamo il codice VB e il codice HTML in due file distinti. Il codice VB è inserito in [heure5.aspx.vb]:
Public Class heure5
Inherits System.Web.UI.Page
' data of the web page to be displayed
Protected maintenant As String
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'calculates the web page data
maintenant = Date.Now.ToString("T")
End Sub
End Class
Il codice HTML è inserito in [heure5.aspx]:
<%@ Page Inherits="heure5" %>
<html>
<head>
<title>Demo asp.net</title>
</head>
<body>
Il est
<% =maintenant %>
</body>
</html>
Questa volta, la direttiva [Page] non specifica più il collegamento tra il codice HTML e il codice VB. Il server web non è più in grado di individuare il codice VB per compilarlo (manca l'attributo src). Spetta a noi eseguire questa compilazione. In una finestra DOS, compiliamo quindi la classe VB [heure5.aspx.vb]:
dos>dir
23/03/2004 18:34 133 heure1.aspx
24/03/2004 09:47 232 heure2.aspx
24/03/2004 10:16 183 heure3.aspx
24/03/2004 10:16 332 heure3.aspx.vb
24/03/2004 14:31 440 heure4.aspx
24/03/2004 14:45 332 heure5.aspx.vb
24/03/2004 14:56 148 heure5.aspx
dos>vbc /r:system.dll /r:system.web.dll /t:library /out:heure5.dll heure5.aspx.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
Nell'esempio sopra riportato, l'eseguibile del compilatore [vbc.exe] si trovava nel PATH del computer DOS. Se così non fosse stato, sarebbe stato necessario specificare il percorso completo di [vbc.exe], che si trova nella struttura di directory in cui è stato installato l'SDK .NET. Le classi derivate da [Page] richiedono risorse presenti nelle DLL [system.dll, system.web.dll], da qui il riferimento a esse tramite l'opzione /r del compilatore. L'opzione /t:library viene utilizzata per indicare che si desidera generare una DLL. L'opzione /out specifica il nome del file da generare, in questo caso [heure5.dll]. Questo file contiene la classe [heure5] richiesta dal documento web [heure5.aspx]. Tuttavia, il server web cerca le DLL di cui ha bisogno in posizioni specifiche. Una di queste posizioni è la cartella [bin] situata alla radice della sua struttura di directory. Questa radice è quella che abbiamo chiamato <webroot>. Per il server IIS, si tratta generalmente di <drive>:\inetpub\wwwroot, dove <drive> è l'unità (C, D, ...) su cui è stato installato IIS. Per il server Cassini, questa radice corrisponde al parametro /path utilizzato al momento del suo avvio. Ricordate che questo valore può essere ottenuto facendo doppio clic sull'icona del server nella barra delle applicazioni:

<webroot> corrisponde all'attributo [Physical Path] sopra indicato. Creiamo quindi una cartella <webroot>\bin e inseriamo [heure5.dll] al suo interno:

Siamo pronti. Richiediamo l'URL [http://localhost/aspnet/chap2/heure5.aspx] dal server Cassini (<webroot>,/aspnet):

3.3.6. Esempio di base - Variante 6
Strumenti necessari: un editor di testo, il server web Cassini
Abbiamo dimostrato finora che un'applicazione web dinamica ha due componenti:
- codice VB per calcolare le parti dinamiche della pagina
- Codice HTML, che a volte include codice VB per visualizzare questi valori nella pagina. Questa parte rappresenta la risposta inviata al client web.
Il componente 1 è chiamato componente controller della pagina, mentre il componente 2 è il componente di presentazione. Il componente di presentazione dovrebbe contenere il minor codice VB possibile, o addirittura nessun codice VB. Vedremo che ciò è possibile. Qui mostriamo un esempio in cui è presente solo un controller e nessun componente di presentazione. È il controller stesso a generare la risposta al client senza l'aiuto del componente di presentazione.
Il codice di presentazione diventa il seguente:
Possiamo notare che all'interno non è più presente alcun codice HTML. La risposta viene generata direttamente nel controller:
Public Class heure6
Inherits System.Web.UI.Page
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' we work out the answer
Dim HTML As String
HTML = "<html><head><title>heure6</title></head><body>Il est "
HTML += Date.Now.ToString("T")
HTML += "</body></html>"
' we send it
Response.Write(HTML)
End Sub
End Class
Qui, il controller costruisce l'intera risposta anziché solo le sue parti dinamiche. Inoltre, la invia. Lo fa utilizzando la proprietà [Response] di tipo [HttpResponse] nella classe [Page]. Questo oggetto rappresenta la risposta del server al client. La classe [HttpResponse] dispone di un metodo [Write] per la scrittura nel flusso HTML che verrà inviato al client. Qui, memorizziamo l'intero flusso HTML da inviare nella variabile [HTML] e lo inviamo al client utilizzando [Response.Write(HTML)].
Richiediamo l'URL [http://localhost/aspnet/chap2/heure6.aspx] dal server Cassini (<webroot>,/aspnet):

3.3.7. Conclusione
Successivamente, utilizzeremo il Metodo 3, che colloca il codice VB e il codice HTML di un documento web dinamico in due file separati. Questo metodo ha il vantaggio di suddividere una pagina web in due componenti:
- una componente di controllo costituita esclusivamente da codice VB per calcolare le parti dinamiche della pagina
- un componente di presentazione, che è la risposta inviata al client. Consiste in codice HTML che può includere codice VB per la visualizzazione di valori dinamici. Cercheremo sempre di avere il minor codice VB possibile nel componente di presentazione; idealmente, nessuno.
Come mostrato nel Metodo 5, il controller può essere compilato indipendentemente dall'applicazione web. Ciò ha il vantaggio di consentire di concentrarsi esclusivamente sul codice e di ricevere un elenco di tutti gli errori ad ogni compilazione. Una volta compilato il controller, l'applicazione web può essere testata. Senza una compilazione preventiva, sarà il server web a occuparsene e gli errori verranno segnalati uno per uno. Ciò può essere considerato noioso.
Per gli esempi che seguono, sono sufficienti i seguenti strumenti:
- un editor di testo per creare i documenti HTML e VB dell'applicazione quando sono semplici
- un IDE di sviluppo .NET per creare classi VB.NET, in modo da beneficiare dell'assistenza che questo tipo di strumento fornisce durante la scrittura del codice. Un esempio di tale strumento è CSharpDevelop (http://www.icsharpcode.net). Un esempio del suo utilizzo è mostrato nell'appendice [Strumenti di sviluppo web].
- lo strumento WebMatrix per creare le pagine di presentazione dell'applicazione (vedere l'appendice [Strumenti di sviluppo Web]).
- Il server Cassini
Tutti questi strumenti sono gratuiti.