Skip to content

5. Gestione dell’interfaccia utente

5.1. Introduction

Nella relazione client-server del web, il client trasmette informazioni al server sotto forma di stringa di parametri [param1=val1&param2=val2&...]. Nei nostri esempi precedenti, abbiamo costruito questa stringa il più delle volte manualmente, richiedendo URL della forma [http://localhost/appli? param1=val1&param2=val2&...]. In realtà, le informazioni che il client trasmette al server provengono dai moduli compilati dall’utente. In questo capitolo esploreremo la loro creazione. Introdurremo inoltre lo strumento WebMatrix che ci consentirà di progettare le interfacce utente. L’installazione di questo strumento è descritta negli allegati.

5.2. Il linguaggio HTML

5.2.1. Un esempio

Consideriamo il seguente esempio, creato con [Web Matrix], che presenta:

  • una tabella
  • un'immagine
  • un link

Image

Eseguiamo [WebMatrix] e poi selezioniamo l'opzione [File/New File]:

Image

Scegliamo di creare una pagina HTML. Le informazioni sopra riportate creeranno un file [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm]. [WebMatrix] offre due possibilità per modificare questo file: la modalità [Design] e la modalità [HTML]:

Image

La modalità [Design] consente di utilizzare la tavolozza dei componenti HTML offerta da [WebMatrix]:

Image

Per inserire un elemento di questa tavolozza, è sufficiente fare doppio clic su di esso e poi posizionarlo nella finestra [Design]. La modalità [HTML] consente di creare il documento HTML utilizzando un editor di testo. A tal fine è necessario conoscere la sintassi del linguaggio HTML. Nella scheda [HTML] è stato generato uno scheletro di documento:

Image

La finestra [HTML] è molto utile per chi non conosce il linguaggio HTML. L'utente crea il proprio documento nella finestra [Design] e verifica il codice HTML generato nella finestra [HTML]. In questo modo acquisisce progressivamente padronanza di HTML e può abbastanza rapidamente lavorare esclusivamente con l’editor di testo senza l’ausilio della modalità [Design]. Mostreremo ora come costruire il documento HTML presentato all’inizio di questa sezione. Lavoriamo nella finestra [Design]. Innanzitutto, inseriamo direttamente la prima riga di testo:

Image

  • aggiungiamo il componente [Horizontal Rule] nella tavolozza dei componenti:

Image

  • aggiungiamo il componente [Table]:

Image

  • posizioniamo il cursore sulla terza riga della tabella per eliminarla con l'opzione [HTML/Edit Table/Delete Table Row]. Quindi inseriamo il testo desiderato in ogni cella:

Image

  • posizioniamo il cursore in una delle celle della tabella e ne esaminiamo le proprietà. La finestra delle proprietà è visualizzata in basso a destra nell’area di lavoro:

Image

  • la cella è rappresentata dal tag HTML <TD>. Ci vengono quindi mostrate le proprietà del tag <TD>. Ci concentriamo sulla tabella, che è un oggetto che racchiude la cella. Facciamo clic sull'elenco a discesa (click to see parent HTML elements) qui sopra per selezionare l'oggetto <TABLE>:

Image

  • L’oggetto <TABLE> ha una proprietà [border] che definisce la larghezza del bordo che circonda le celle della tabella. In questo caso, impostiamo border=1.

Image

  • Modifichiamo ora gli attributi dell’oggetto <TD> della cella (1,2) per impostare align=Center e width=200 (pixel). Il testo sarà centrato nella cella (align=center) e questa avrà una larghezza di 200 pixel. Per visualizzare la modifica, a volte potrebbe essere necessario selezionare la scheda [HTML] e poi tornare alla scheda [Design]:

Image

  • ora inseriamo il testo che precede l’immagine:

Image

  • poi l’immagine facendo doppio clic sul componente [image] dalla tavolozza:

Image

  • selezioniamo l'immagine per modificarne le proprietà:

Image

  • nell’attributo [src], inseriamo il nome del file contenente l’immagine, in questo caso [univ01.gif]:

Image

  • inseriamo il testo che precede il link:

Image

  • trasformiamo il testo [ici] in un link all'URL [http://istia.univ-angers.fr]. Per farlo, lo selezioniamo e poi scegliamo l'opzione [HTML/Insert Hyperlink]:

Image

  • otteniamo il seguente risultato:

Image

  • ci siamo quasi. Diamo un’occhiata al codice HTML generato nella scheda [HTML]:
<html>
<head>
</head>
<body>
    <p>
        Le langage HTML - 1 
    </p>
    <hr />
    <table border="1">
        <tbody>
            <tr>
                <td>
                    cellule(1,1)</td>
                <td align="middle" width="200">
                    cellule(1,2)</td>
                <td>
                    cellule(1,3)</td>
            </tr>
            <tr>
                <td>
                    cellule(2,1)</td>
                <td>
                    cellule(2,2)</td>
                <td>
                    cellule(2,3)</td>
            </tr>
        </tbody>
    </table>
    <p>
        Une image <img src="univ01.gif" /> 
    </p>
    <p>
        Le site de l'istia <a href="http://istia.univ-angers.fr">ici</a>
    </p>
</body>
</html>

Ci restano ancora alcuni dettagli da sistemare. Innanzitutto vorremmo assegnare un titolo al nostro documento. [WebMatrix] non consente di farlo in modalità [Design]. Nella scheda [HTML] sostituiamo la sequenza <head>..</head> con la seguente sequenza:

<head>
    <title>HTML1</title>
</head>

Inoltre, vorremmo che il testo [Le langage HTML - 1] fosse visualizzato con caratteri più grandi. La sequenza <Hi>testo</Hi> consente di impostare la dimensione di un testo con i che varia da 1 a 6, dal più grande al più piccolo. In questo caso, sceglieremo H2. La sequenza

    <p>
        Le langage HTML - 1 
    </p>

diventa:

<h2>Le langage HTML - 1</h2>

La finestra [Design] riflette le nostre modifiche:

Image

Non ci resta che eseguire il test utilizzando l'opzione [View/Start] o [F5]. L'opzione [WebMatrix] richiede alcune informazioni per avviare il server Web [Cassini]:

Image

Possiamo accettare i valori predefiniti. Il server [Cassini] viene avviato e la nostra pagina viene visualizzata in un browser:

Image

Per curiosità, possiamo verificare con quali parametri è stato avviato [Cassini]:

Image

Abbiamo illustrato le basi per la creazione di una pagina HTML con [WebMatrix]. Il lettore è invitato a creare altre pagine HTML e a verificare ogni volta il codice HTML generato. A poco a poco, sarà in grado di creare una pagina senza l’ausilio della modalità [Design]. Un documento HTML ha la seguente struttura generale:

<html>
    <head>
        <title>Un titre</title>
        ...
    </head>
    <body attributs>
        ...
    </body>
</html>

L'intero documento è racchiuso tra i tag <html>...</html>. È composto da due parti:

<head>...</head>: è la parte non visibile del documento. Fornisce informazioni al browser che visualizzerà il documento. Spesso vi si trova il tag <title>...</title>, che definisce il testo che verrà visualizzato nella barra del titolo del browser. Vi si possono trovare anche altri tag, in particolare quelli che definiscono le parole chiave del documento, parole chiave che verranno poi utilizzate dai motori di ricerca. In questa parte si possono trovare anche degli script, scritti per lo più in JavaScript o VBScript, che verranno eseguiti dal browser.

<body attributi>...</body>: è la parte che verrà visualizzata dal browser. I tag HTML contenuti in questa sezione indicano al browser l’aspetto visivo “desiderato” per il documento. Ogni browser interpreterà questi tag a modo suo. Due browser possono quindi visualizzare in modo diverso lo stesso documento web. Questo rappresenta generalmente uno dei grattacapi dei web designer.

Il codice HTML del documento precedente era il seguente:

<html>
<head>
    <title>HTML1</title>
</head>
<body>
    <h2>Le langage HTML - 1 
    </h2>
    <hr />
    <table border="1">
        <tbody>
            <tr>
                <td>
                    cellule(1,1)</td>
                <td align="middle" width="200">
                    cellule(1,2)</td>
                <td>
                    cellule(1,3)</td>
            </tr>
            <tr>
                <td>
                    cellule(2,1)</td>
                <td>
                    cellule(2,2)</td>
                <td>
                    cellule(2,3)</td>
            </tr>
        </tbody>
    </table>
    <p>
        Une image <img src="univ01.gif" /> 
    </p>
    <p>
        Le site de l'istia <a href="http://istia.univ-angers.fr">ici</a> 
    </p>
</body>
</html>
Elemento
tag ed esempi HTML
titre du document
<title>HTML1</title>
HTML1 apparirà nella barra del titolo del browser che visualizzerà il documento
barre horizontale
<hr>: visualizza una linea orizzontale
tableau
<attributi tabella>....</table>: per definire la tabella
<tr attributi>...</tr>: per definire una riga
<td attributi>...</td>: per definire una cella
esempi:
<table border="1">...</table>: l'attributo border definisce lo spessore del bordo della tabella
<td align="center" width="200">cella(1,2)</td>: definisce una cella il cui contenuto sarà cellule(1,2). Questo contenuto sarà centrato orizzontalmente (align="center"). La cella avrà una larghezza di 200 pixel (width="200")
image
<img src="univ01.gif" />: definisce un'immagine il cui file sorgente è univ01.gif sul server web (src="univ01.gif"). Questo link si trova in un documento web generato con URL http://localhost/exemple1.htm. Pertanto, il browser richiederà l'URL http://localhost/univ01.gif per ottenere l'immagine qui referenziata.
lien
<a href="http://istia.univ-angers.fr">qui</a>: fa sì che il testo ici funga da link verso l'URL http://istia.univ-angers.fr.

Da questo semplice esempio si evince che, per costruire l’intero documento, il browser deve effettuare due richieste al server:

http://localhost/exemple1.htm per ottenere il codice sorgente HTML del documento

http://localhost/univ01.gif per ottenere l'immagine univ01.gif

5.2.2. Creazione di un modulo

Un modulo HTML ha lo scopo di presentare all'utente una pagina di inserimento dati simile ai moduli di inserimento presenti in Windows. Il modulo di inserimento viene inviato al browser sotto forma di documento HTML. Quest’ultimo mostrerà il modulo all’utente, che lo compilerà e lo convaliderà tramite un pulsante dedicato. Il browser trasmetterà quindi i valori inseriti al server per l’elaborazione. Si noterà che non viene inviato al server l’intero modulo, ma solo i valori inseriti. L’esempio seguente presenta un modulo Web creato anch’esso con WebMatrix:

Image

Il codice HTML generato da [WebMatrix] è il seguente:


<html>
    <head>
        <title>Formulaire</title>
        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        </script>
    </head>
    <body>
        <p>
            Gestion d'un formulaire
        </p>
        <hr />
        <form name="formulaire" method="post">
            <table border="1">
                <tr>
                    <td>
                        Etes-vous marié(e)</td>
                    <td>
                        <p align="center">
                            <input type="radio" value="oui" name="rdMarie" />Oui 
                            <input type="radio" checked value="non" name="rdMarie" />Non
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Cases à cocher
                    </td>
                    <td>
                        <p align="center">
                            <input type="checkbox" value="un" name="C1" />1
                            <input type="checkbox" checked value="deux" name="C2" />2
                            <input type="checkbox" value="trois" name="C3" />3
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Champ de saisie</td>
                    <td>
                        <p align="center">
                            <input type="text" maxlength="30" value="qqs mots" name="txtSaisie" />
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Mot de passe</td>
                    <td>
                        <p align="center">
                            <input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Boîte de saisie</td>
                    <td>
                        <p align="center">
                        </p>
                        <textarea name="areaSaisie">ligne1
ligne2</textarea>
                    </td>
                </tr>
                <tr>
                    <td>
                        ComboBox</td>
                    <td>
                        <p align="center">
                        </p>
                        <select name="cmbValeurs">
                            <option value="1">choix1</option>
                            <option value="2" selected>choix2</option>
                            <option value="3">choix3</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        Liste à choix simple</td>
                    <td>
                        <p align="center">
                        </p>
                        <select size="3" name="lstSimple">
                            <option value="1" selected>liste1</option>
                            <option value="2">liste2</option>
                            <option value="3">liste3</option>
                            <option value="4">liste4</option>
                            <option value="5">liste5</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        Liste à choix multiple</td>
                    <td>
                        <p align="center">
                        </p>
                        <select multiple size="3" name="lstMultiple">
                            <option value="1" selected>multiple1</option>
                            <option value="2">multiple2</option>
                            <option value="3" selected>multiple3</option>
                            <option value="4">multiple4</option>
                            <option value="5">multiple5</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton simple</td>
                    <td>
                        <p align="center">
                            <input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" />
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton submit</td>
                    <td>
                        <p align="center">
                            <input type="submit" value="Envoyer" name="btnEnvoyer" />
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton reset</td>
                    <td>
                        <p align="center">
                            <input type="reset" value="Rétablir" name="btnRetablir" runat="server" />
                        </p>
                    </td>
                </tr>
            </table>
            <input type="hidden" name="secret" value="uneValeur" />
        </form>
    </body>
</html>

L'associazione tra controllo visivo <--> tag HTML è la seguente:

Controllo
tag HTML
formulaire
<form name="modulo" method="post">
champ de saisie
<input type="text" maxlength="30" value="alcune parole" name="txtSaisie" />
champ de saisie cachée
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
champ de saisie multilignes
<textarea name="areaSaisie">riga1
riga2</textarea>
boutons radio
<input type="radio" value="sì" name="rdMarie" />
<input type="radio" checked value="no" name="rdMarie" />No
cases à cocher
<input type="checkbox" value="uno" name="C1" />1
<input type="checkbox" checked value="due" name="C2" />2
<input type="checkbox" value="tre" name="C3" />3
Combo
<select name="cmbValeurs">
<option value="1">scelta1</option>
<option value="2" selected>opzione2</option>
<option value="3">scelta3</option>
</select>
liste à sélection unique
<select size="3" name="lstSimple">
<option value="1" selected>elenco1</option>
<option value="2">elenco2</option>
<option value="3">lista3</option>
<option value="4">lista4</option>
<option value="5">lista5</option>
</select>
liste à sélection multiple
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>
champ caché
<input type="hidden" name="secret" value="uneValeur" />
bouton de type submit
<input type="submit" value="Invia" name="btnEnvoyer" />
bouton de type reset
<input type="reset" value="Ripristina" name="btnRetablir" runat="server" />
bouton de type button
<input onclick="effacer()" type="button" value="Cancella" name="btnEffacer" />

Esaminiamo questi diversi controlli.

5.2.2.1. Il modulo

formulaire
<form name="modulo" method="post">
balise HTML
<form name="..." method="..." action="...">...</form>
attributs
name="frmexemple": nome del modulo
method="..." : metodo utilizzato dal browser per inviare al server web i valori raccolti nel modulo
action="..." : URL a cui verranno inviati i valori raccolti nel modulo.
Un modulo web è racchiuso tra i tag <form>...</form>. Il modulo può avere un nome (name="xx"). Questo vale per tutti i controlli presenti in un modulo. Tale nome è utile se il documento web contiene script che devono fare riferimento agli elementi del modulo. Lo scopo di un modulo è quello di raccogliere le informazioni fornite dall’utente tramite tastiera o mouse e di inviarle a una pagina web del server. Quale? Quella indicata nell’attributo action="URL". Se questo attributo è assente, le informazioni verranno inviate al server del documento in cui si trova il modulo. In che modo un client web trasmette le informazioni (quelle contenute nel modulo) a un server web? Lo abbiamo visto in dettaglio. Può utilizzare due metodi diversi denominati POST e GET. L’attributo method="méthode", con il metodo impostato su GET o POST, del tag <form> indica al browser il metodo da utilizzare per inviare le informazioni raccolte nel modulo all'URL specificato dall'attributo action="URL". Quando l'attributo method non è specificato, viene utilizzato per impostazione predefinita il metodo GET.

5.2.2.2. Campo di immissione

Image

champ de saisie
<input type="text" maxlength="30" value="alcune parole" name="txtSaisie" />
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
balise HTML
<input type="..." name="..." size=".." value="..">
Il tag input è disponibile per diversi controlli. È l'attributo type che permette di distinguere questi diversi controlli tra loro.
attributs
type="text": specifica che si tratta di un campo di immissione
type="password": i caratteri presenti nel campo di immissione vengono sostituiti da asterischi (*). È l'unica differenza rispetto al campo di immissione normale. Questo tipo di controllo è adatto per l'immissione delle password.
size="12": numero di caratteri visibili nel campo - non impedisce l'inserimento di un numero maggiore di caratteri
maxlength="30": imposta a 30 il numero massimo di caratteri; spetta al browser garantire il rispetto di questo attributo
name="txtSaisie": nome del controllo
value="alcune parole": testo che verrà visualizzato nel campo di immissione.

5.2.2.3. Campo di immissione multilinea

Image

champ de saisie multilignes
<textarea name="areaSaisie">riga1
riga2</textarea>
balise HTML
<textarea ...>testo</textarea>
visualizza un campo di immissione multilinea con del testo precompilato
attributs
rows="2": numero di righe
cols="'20" : numero di colonne
name="areaSaisie": nome del controllo

5.2.2.4. Pulsanti di opzione

Image

boutons radio
<input type="radio" value="sì" name="rdMarie" />
<input type="radio" checked value="no" name="rdMarie" />No
balise HTML
<input type="radio" attributo2="valore2" ..../>testo
visualizza un pulsante di opzione con del testo accanto.
attributs
name="rdMarie": nome del controllo. I pulsanti di opzione con lo stesso nome formano un gruppo di pulsanti mutuamente esclusivi: è possibile selezionare solo uno di essi.
value="valore": valore assegnato al pulsante di opzione. Non bisogna confondere questo valore con il testo visualizzato accanto al pulsante di opzione, che serve solo a scopo di visualizzazione.
checked: se questa parola chiave è presente, il pulsante di opzione è selezionato, altrimenti non lo è.

5.2.2.5. Caselle di controllo

cases à cocher
<input type="checkbox" value="uno" name="C1" />1
<input type="checkbox" checked value="due" name="C2" />2
<input type="checkbox" value="tre" name="C3" />3

Image

balise HTML
<input type="checkbox" attributo2="valore2" ..../>testo
visualizza una casella di controllo con del testo accanto.
attributs
name="C1": nome del controllo. Le caselle di controllo possono avere o meno lo stesso nome. Le caselle con lo stesso nome formano un gruppo di caselle associate.
value="valore": valore assegnato alla casella di controllo. Non bisogna confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Quest'ultimo è destinato esclusivamente alla visualizzazione.
checked: se questa parola chiave è presente, il pulsante di opzione è selezionato, altrimenti non lo è.

5.2.2.6. Elenco a discesa (combo)

Combo
<select name="cmbValeurs">
<option value="1">scelta1</option>
<option value="2" selected>scelta2</option>
<option value="3">opzione 3</option>
</select>

Image

balise HTML
<select size=".." name="..">
<option [selected="selected"] [value="valeur"]>testo</option>
...
</select>
visualizza in un elenco i testi compresi tra i tag <option>...</option>
attributs
name="cmbValeurs": nome del controllo.
size="1": numero di elementi visibili nell'elenco. size="1" rende l'elenco equivalente a una casella combinata. È il valore predefinito se l'attributo [size] è assente.
selected="selected": se questo attributo è presente per un elemento dell'elenco, quest'ultimo appare selezionato nell'elenco. Nel nostro esempio sopra riportato, l'elemento dell'elenco choix2 appare come elemento selezionato nel menu a tendina quando questo viene visualizzato per la prima volta.
value="valore": imposta il valore da inviare al server se l'elemento viene selezionato. Se questo attributo è assente, al server viene inviato il testo associato all'opzione.

5.2.2.7. Elenco a selezione singola

liste à sélection unique
<select size="3" name="lstSimple">
<option value="1" selected>lista1</option>
<option value="2">lista2</option>
<option value="3">elenco3</option>
<option value="4">lista4</option>
<option value="5">elenco5</option>
</select>

Image

balise HTML
<select size=".." name="..">
<option [selected] [value="valeur"]>...</option>
...
</select>
visualizza in un elenco i testi compresi tra i tag <option>...</option>
attributs
gli stessi utilizzati per l'elenco a discesa che visualizza un solo elemento. Questo controllo differisce dall'elenco a discesa precedente solo per l'attributo size>1.

5.2.2.8. Elenco a selezione multipla

liste à sélection multiple
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>

Image

balise HTML
<select size=".." name=".." multiple>
<option [selected] ] [value="valeur"]>...</option>
...
</select>
visualizza in un elenco i testi compresi tra i tag <option>...</option>
attributs
multiple: consente la selezione di più elementi nell'elenco. Nell'esempio sopra riportato, gli elementi liste1 e liste3 sono entrambi selezionati.

5.2.2.9. Pulsante di tipo button

bouton de type button
<input onclick="effacer()" type="button" value="Cancella" name="btnEffacer" />

Image

balise HTML
<input type="button" value="..." name="..." onclick="effacer()" ....>
attributs
type="button": definisce un controllo pulsante. Esistono altri due tipi di pulsante: submit e reset.
value="Cancella": il testo visualizzato sul pulsante
onclick="funzione()": consente di definire una funzione da eseguire quando l'utente fa clic sul pulsante. Questa funzione fa parte degli script definiti nel documento web visualizzato. La sintassi precedente è una sintassi javascript. Se gli script sono scritti in VBScript, occorre scrivere onclick="funzione" senza le parentesi. La sintassi rimane identica se è necessario passare dei parametri alla funzione: onclick="funzione(val1, val2,...)"
Nel nostro esempio, un clic sul pulsante Effacer richiama la seguente funzione JavaScript effacer:

        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        </script>
La funzione effacer visualizza un messaggio:

5.2.2.10. Pulsante di tipo «submit»

bouton de type submit
<input type="submit" value="Invia" name="btnEnvoyer" />

Image

balise HTML
<input type="submit" value="Invia" name="btnEnvoyer">
attributs
type="submit": definisce il pulsante come pulsante di invio dei dati del modulo al server web. Quando l'utente clicca su questo pulsante, il browser invia i dati del modulo all'URL URL definito nell'attributo action del tag <form> secondo il metodo definito dall'attributo method dello stesso tag.
value="Invia": il testo visualizzato sul pulsante

5.2.2.11. Pulsante di tipo reset

bouton de type reset
<input type="reset" value="Ripristina" name="btnRetablir" runat="server" />

Image

balise HTML
<input type="reset" value="Ripristina" name=" btnRetablir ">
attributs
type="reset": definisce il pulsante come pulsante di ripristino del modulo. Quando l'utente fa clic su questo pulsante, il browser riporta il modulo allo stato in cui lo ha ricevuto.
value="Ripristina": il testo visualizzato sul pulsante

5.2.2.12. Campo nascosto

champ caché
<input type="hidden" name="secret" value="uneValeur" />
balise HTML
<input type="hidden" name="..." value="...">
attributs
type="hidden": specifica che si tratta di un campo nascosto. Un campo nascosto fa parte del modulo ma non viene mostrato all'utente. Tuttavia, se l'utente richiedesse al proprio browser di visualizzare il codice sorgente, vedrebbe la presenza del tag <input type="hidden" value="..."> e quindi il valore del campo nascosto.
value="unValore": valore del campo nascosto.
A cosa serve il campo nascosto? Può consentire al server web di conservare informazioni nel corso delle richieste di un cliente. Consideriamo un'applicazione per gli acquisti online. Il cliente acquista un primo articolo art1 in quantità q1 su una prima pagina di un catalogo, quindi passa a una nuova pagina del catalogo. Per ricordare che il cliente ha acquistato q1 articoli art1, il server può inserire queste due informazioni in un campo nascosto del modulo web della nuova pagina. In questa nuova pagina, il cliente acquista gli articoli q2 e art2. Quando i dati di questo secondo modulo verranno inviati al server (submit), quest’ultimo riceverà non solo le informazioni (q2,art2), ma anche (q1,art1), che fa anch’esse parte del modulo come campi nascosti non modificabili dall’utente. Il server web inserirà quindi in un nuovo campo nascosto le informazioni (q1,art1) e (q2,art2) e invierà una nuova pagina del catalogo. E così via.

5.3. Invio dei valori di un modulo da un browser a un server web

Sappiamo già, grazie al capitolo precedente, come un client invia informazioni al server. Lo fa tramite:

  • una richiesta HTTP GET url?param1=va1&param2=val2&....
  • una richiesta HTT POST url seguita da un documento contenente la stringa di parametri param1=va1&param2=val2&....

Il browser utilizzerà uno di questi due metodi a seconda che l’attributo [method] del tag [form] sia GET o POST. È proprio ciò che mostreremo ora. La pagina esaminata in precedenza è una pagina statica. Per poter accedere alle intestazioni HTTP inviate dal browser che richiederà questo documento, la trasformiamo in una pagina dinamica per un server web .NET (IIS o Cassini). Il codice statico precedente viene inserito in un file [formulaire_get.aspx] e il suo contenuto è il seguente:


<%@ Page src="formulaire_get.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire_get" %>
<html>
    <head>
        <title>Formulaire</title>
        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        </script>
    </head>
    <body>
.....
    </body>
</html>

La pagina di presentazione sopra riportata è associata al controller [formulaire_get.aspx.vb]:


Public Class formulaire_get
    Inherits System.Web.UI.Page

    Private Sub Page_Init(ByVal Sender As Object, ByVal e As System.EventArgs) Handles MyBase.Init
        ' salva la richiesta corrente in request.txt nella cartella della pagina
        Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
        Me.Request.SaveAs(requestFileName, True)
    End Sub
End Class

Ad ogni richiamo del documento [formulaire_get.aspx], la richiesta del cliente verrà salvata in un file [request.txt] tramite la procedura Page_Init. Abbiamo già incontrato questa modalità di funzionamento, pertanto non forniremo ulteriori commenti sul controller.

5.3.1. Metodo GET

Effettuiamo un primo test: nel codice HTML del documento, il tag FORM è definito come segue:


        <form name="formulaire" method="get">

Inseriamo i file [formulaire_get.aspx] e [formulaire_get.aspx.vb] in una cartella <application-path> e avviamo il server Cassini con i parametri (<application-path>,/form2). Richiediamo l'URL http://localhost/form2/formulaire_get.aspx:

Image

Il browser ha appena effettuato una richiesta e sappiamo che questa è stata salvata nel file [request.txt]. Diamo un’occhiata al suo contenuto:

GET /form2/formulaire_get.aspx HTTP/1.1
Cache-Control: max-age=0
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

Il browser ha utilizzato una richiesta HTTP GET per richiedere l'URL [http://localhost/form2/formulaire_get.aspx]. Questo accade sempre quando l'URL viene fornito dall'utente. Il modulo viene compilato nel modo seguente:

Image

Utilizziamo il pulsante [Envoyer] sopra indicato. Il suo codice HTML è il seguente:

<form method="get">
    ...
    <input type="submit" value="Envoyer">
    ...
</form>

All'attivazione di un pulsante di tipo [Submit], il browser invia i parametri del modulo (tag <form>) all'URL indicato nell'attributo [action] del tag <form action="URL">, se presente. Se tale attributo non esiste, i parametri del modulo vengono inviati all'URL che ha generato il modulo. È questo il caso in questione. Il pulsante [Envoyer] dovrebbe quindi generare una richiesta del browser all’URL [http://localhost/form2/formulaire_get.aspx] con il trasferimento dei parametri del modulo. Poiché la pagina [formulaire_get.aspx] memorizza la richiesta ricevuta, dovremmo essere in grado di capire come il client abbia trasferito tali parametri. Proviamo. Facciamo clic sul pulsante [Envoyer]. Riceviamo la seguente risposta dal browser:

Image

Si tratta della pagina iniziale, ma si può notare che il valore URL nel campo [Adresse] del browser è cambiato. È diventato il seguente:

http://localhost/form2/formulaire_get.aspx?rdMarie=sì&C1=uno&C2=due&txtSaisie=programmazione+asp.net&txtMdp=unMotDePasse&areaSaisie=le+basi+della%0D%0Aprogrammazione+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Invia&secret=uneValeur

Si nota che le scelte effettuate nel modulo si ritrovano nel campo URL. Esaminiamo il contenuto del file [request.txt] che ha memorizzato la richiesta del client:

GET /form2/formulaire_get.aspx?rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/form2/formulaire_get.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

Si nota una richiesta HTTP piuttosto simile a quella inizialmente inviata dal browser quando aveva richiesto il documento senza trasmettere alcun parametro. Ci sono due differenze:

GET URL HTTP/1.1
I parametri del modulo sono stati aggiunti dopo l'ID del documento URL nella forma ?param1=val1&param2=val2&...
Referer
Il cliente indica con questa intestazione HTTP il codice URL del documento che stava visualizzando quando ha effettuato la richiesta

Esaminiamo più da vicino come sono stati passati i parametri nel comando GET URL?param1=valore1&param2=valore2&... HTTP/1.1 dove parami sono i nomi dei controlli del modulo web e valeuri i valori ad essi associati. Di seguito presentiamo una tabella a tre colonne:

  • colonna 1: riporta la definizione di un controllo HTML dell'esempio
  • colonna 2: mostra come viene visualizzato questo controllo in un browser
  • colonna 3: riporta il valore inviato al server dal browser per il controllo della colonna 1 nella forma in cui appare nella richiesta GET dell'esempio
controllo HTML
visualizzazione prima della convalida
valore/i restituito/i
<input type="radio" value="sì" name="rdMarie" />Sì
<input type="radio" checked
value="no" name="rdMarie" />No
rdMarie=sì
- il valore dell'attributo value del pulsante
selezionato dall'utente.
<input type="checkbox"
value="uno" name="C1" />1
<input type="checkbox"
checked value="due" name="C2" />2
<input type="checkbox"
value="tre" name="C3" />3
C1=uno
C2=due
- valori degli attributi value delle caselle
selezionate dall'utente
<input type="text" maxlength="30" value="alcune
parole" name="txtSaisie" />
txtInserimento=programmazione+asp.net
- testo digitato dall'utente nel campo
di inserimento. Gli spazi sono stati sostituiti
con il segno +
<input type="password"
maxlength="12" size="12"
value="unaPassword"
name="txtMdp" />
txtMdp=questoÈSegreto
- testo digitato dall'utente nel campo
di immissione. Il testo effettivamente digitato era
"questoèsegreto". L'ultimo carattere è stato
perso perché l'attributo
maxlength="12" limitava il numero di
caratteri a 12.
<textarea name="areaSaisie">
riga1
riga2</textarea>
areaSaisie=le+basi+di+
la%0D%0A
programmazione+web
- testo digitato dall'utente nel campo
di inserimento. %OD%OA è il segno di
fine riga. Gli spazi sono stati
sostituiti dal segno +
<select name="cmbValeurs">
<option value="1">scelta1
</option>
<option value="2" selected>opzione2
</option>
<option value="3">opzione 3
</option>
</select>
cmbValori=3
- valore selezionato dall'utente nell'
elenco a selezione singola
<select size="3"
name="lstSimple">
<option value="1"
selected>lista1</option>
<option value="2">lista2
</option>
<option value="3">lista3
</option>
<option value="4">lista4
</option>
<option value="5">elenco5
</option>
</select>
lstSimple=3
- valore selezionato dall'utente nella
elenco a selezione singola
<select multiple size="3"
name="lstMultiple">
<option value="1" selected>multiple1
</option>
<option value="2">multiple2
</option>
<option value="3" selected>multiple3
</option>
<option value="4">multiple4
</option>
<option value="5">multiple5
</option>
</select>
lstMultiple=2
lstMultiple=4
- valori selezionati dall'utente nell'
elenco a selezione multipla
<input type="submit"
value="Invia"
name="btnInvia" />
btnEnvoyer=Invia
- nome e attributo value del pulsante che è
è stato utilizzato per inviare i dati del modulo
al server
<input type="hidden"
name="secret"
value="unValore" />
 
secret=unValore
- attributo value del campo nascosto

Ci si potrebbe chiedere cosa abbia fatto il server con i parametri che gli sono stati passati. In realtà, nulla. Alla ricezione del comando

GET /form2/formulaire_get.aspx?rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur HTTP/1.1

Il server web ha trasmesso i parametri da URL ai documenti [http://localhost/form2/formulaire_get.aspx] e c.a.d, ovvero al documento che avevamo creato inizialmente. Non abbiamo scritto alcun codice per recuperare ed elaborare i parametri che il client ci invia. Pertanto, è come se la richiesta del client fosse semplicemente:

GET http://localhost/form2/formulaire_get.aspx

È per questo motivo che, in risposta al nostro pulsante [Envoyer], abbiamo ottenuto la stessa pagina ottenuta inizialmente richiedendo URL e [http://localhost/form2/formulaire_get.aspx] senza parametri.

5.3.2. Metodo POST

Il documento HTML è ora configurato in modo che il browser utilizzi il metodo POST per inviare i valori del modulo al server web. A tal fine, copiamo il file [formulaire_get.aspx] in [formulaire_post.aspx] e modifichiamo solo il tag <form> in [formulaire_post.aspx]:


<%@ Page src="formulaire_get.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire_get" %>
<html>
    <head>
        ...
    </head>
    <body>
        <p>
            Gestion d'un formulaire
        </p>
        <hr />
        <form name="formulaire" method="post">
            <table border="1">

Non è necessario sostituire il controller [formulaire_get.aspx.vb], pertanto lo lasciamo così com'è. Richiediamo il nuovo documento tramite URL [http://localhost/form2/formulaire_post.aspx], compiliamo il modulo come per il metodo GET e inviamo i parametri al server con il pulsante [Envoyer]. Dal server otteniamo la seguente pagina di risposta:

Image

Otteniamo quindi lo stesso risultato dei metodi GET e c.a.d: la pagina iniziale. Si noti una differenza: nel campo [Adresse] del browser, i parametri trasmessi non compaiono. Ora esaminiamo la richiesta inviata dal client e memorizzata nel file [request.txt]:

POST /form2/formulaire_post.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Content-Length: 222
Content-Type: application/x-www-form-urlencoded
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/form2/formulaire_post.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

rdMarie=oui&C1=un&C2=deux&txtSaisie=programmation+asp.net&txtMdp=ceciestsecre&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lstSimple=3&lstMultiple=2&lstMultiple=4&btnEnvoyer=Envoyer&secret=uneValeur

Nella richiesta HTTP del cliente compaiono alcune novità:

POST URL HTTP/1.1
la query GET è stata sostituita dalla query POST. I parametri non sono più presenti nella prima riga della query. Si può notare che ora sono posizionati dopo la query HTTP, dopo una riga vuota. La loro codifica è identica a quella che avevano nella query GET.
Content-Length
numero di caratteri “inviati”, c.a.d. Il numero di caratteri che il server web dovrà leggere dopo aver ricevuto le intestazioni HTTP per recuperare il documento inviato dal client. Il documento in questione è in questo caso l’elenco dei valori del modulo.
Content-type
specifica il tipo di documento che il client invierà dopo le intestazioni HTTP. Il tipo [application/x-www-form-urlencoded] indica che si tratta di un documento contenente i valori del modulo.

Esistono due metodi per trasmettere dati a un server web: GET e POST. Esiste un metodo migliore dell’altro? Abbiamo visto che se i valori di un modulo venivano inviati dal browser con il metodo GET, il browser visualizzava nel proprio campo Adresse il valore richiesto URL nella forma URL?param1=val1&param2=val2&.... Questo può essere considerato un vantaggio o uno svantaggio:

  • un vantaggio se si vuole consentire all’utente di inserire questo URL configurato tra i propri link preferiti
  • uno svantaggio se non si desidera che l’utente abbia accesso a determinate informazioni del modulo, come ad esempio i campi nascosti

D'ora in poi, utilizzeremo quasi esclusivamente il metodo POST nei nostri moduli.

5.4. Elaborazione lato server dei valori di un modulo

5.4.1. Presentazione dell’esempio

Ora che abbiamo stabilito il collegamento tra il tag HTML <form method="GET/POST" ...> e il modo in cui il browser invia i valori del modulo, sappiamo come recuperarli sul lato server. È stato il capitolo precedente a fornirci la risposta:

  • se il metodo del tag <form> è GET, i valori dei parametri saranno recuperati nella collezione [Request.QueryString]
  • se il metodo del tag <form> è POST, i valori dei parametri “inviati” saranno recuperati nella collezione [Request.Form]. A questo punto è necessario fare una precisazione. Il tag <form> può specificare, tramite l’attributo [action], l’URL di destinazione del GET o del POST. Tale URL può essere configurato sia che si tratti di un GET sia di un POST, nella forma action="url?param1=val1&param2=val2&..". Questi parametri si aggiungono quindi a quelli contenuti tra i tag <form> e </form>, che saranno oggetto di un trasferimento al server tramite un GET o un POST. Poiché fanno parte dell'URL di destinazione, saranno recuperati nella raccolta [Request.QueryString], indipendentemente dal fatto che si tratti di un GET o di un POST.

Ora scriviamo un'applicazione MVC con due viste:

  • la prima vista è il modulo precedente. La chiameremo [vue_formulaire].
  • la seconda vista è una pagina informativa che elenca i valori inseriti nella prima pagina. Un link consente di tornare al modulo. Chiameremo questa vista [vue_confirmation].

La vista [vue_formulaire] viene inviata all’utente, che la compila e la convalida. Potrebbe apparire così poco prima della convalida:

Image

L’utente utilizza il pulsante [Envoyer] per confermare i dati inseriti. In cambio riceve la seguente vista [vue_validation]:

Image

5.4.2. Il controller dell'applicazione

Nel capitolo precedente abbiamo visto che è possibile affidare il ruolo di controller di un'applicazione MVC al file [global.asax], attraverso il quale transitano tutte le richieste dei client. Abbiamo già presentato un'applicazione MVC costruita in questo modo e qui seguiamo il modello di sviluppo presentato in quell'occasione. Il file [global.asax] sarà il seguente:

<%@ Application src="Global.asax.vb" Inherits="Global" %>

È costituito da un’unica riga che fa riferimento al controller contenuto nel file [global.asax.vb]:


Imports System
Imports System.Web
Imports System.Web.SessionState

Public Class Global
    Inherits System.Web.HttpApplication

    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' si recupera l'azione da eseguire
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' si esegue l'azione
        Select Case action
            Case "init"
                Server.Transfer("formulaire.aspx", False)
            Case "validation"
                Server.Transfer("validation.aspx", True)
            Case Else
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub
End Class

Il funzionamento del controller è il seguente:

  • il controller verifica la presenza, nell'URL di destinazione, di una stringa di parametri contenente il parametro [action]. Se questo parametro è assente, il sistema si comporta come se nella stringa di parametri fosse presente [action=init].
  • Sono riconosciute solo due azioni:
    • init: al cliente viene fornito il modulo precompilato
    • validation: al cliente viene inviata la pagina che conferma i dati inseriti
  • se l'azione non è una delle precedenti, si procede come se fosse presente [action=init]. Si potrebbe anche visualizzare una pagina di errore.

5.4.3. Elaborazione dell'azione init

Quando il controller elabora l’azione «init», deve generare un modulo precompilato. È compito della pagina [formulaire.aspx] svolgere questo compito. Il suo codice è il seguente:


<HTML>
    <HEAD>
        <title>Formulaire</title>
        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        function raz(liste){
            liste.selectedIndex=-1
        }
        </script>
    </HEAD>
    <body>
        <p>
            Gestion d'un formulaire
        </p>
        <hr>
        <form name="formulaire" method="post" action="?action=validation">
            <table border="1">
                <tr>
                    <td>
                        Etes-vous marié(e)</td>
                    <td>
                        <p align="center">
                            <input type="radio" value="oui" name="rdMarie">Oui <input type="radio" checked value="non" name="rdMarie">Non
                        </p>
                    </td>
                </tr>
....
                    <td>
                        <select size="3" name="lstSimple">
                            <option value="1" selected>liste1</option>
                            <option value="2">liste2</option>
                            <option value="3">liste3</option>
                            <option value="4">liste4</option>
                            <option value="5">liste5</option>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
                    </td>
....
                    <td>
                        <select multiple size="3" name="lstMultiple">
                            <option value="1" selected>multiple1</option>
                            <option value="2">multiple2</option>
                            <option value="3" selected>multiple3</option>
                            <option value="4">multiple4</option>
                            <option value="5">multiple5</option>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
                    </td>
...

            </table>
            <input type="hidden" name="secret" value="uneValeur">
        </form>
    </body>
</HTML>

Ritroviamo il codice HTML del modulo esaminato in precedenza, con alcune differenze. Il codice del tag <form> è stato modificato:


        <form name="formulaire" method="post" action="?action=validation">
  • post: i valori inseriti dall’utente e inviati al server quando verrà utilizzato il pulsante di tipo [submit] saranno inviati tramite il metodo HTTP POST
  • azione: la sintassi action="url" serve a indicare l'URL a cui devono essere inviati i valori del modulo. Questo URL può includere una stringa di parametri nella forma param1=val1&param2=val2&... È ciò che avviene in questo caso, in cui passiamo il parametro [action=validation] per indicare al controller l’azione che deve intraprendere. Si noti che questa stringa di parametri non è preceduta da un indirizzo web. Il browser invierà quindi i parametri del modulo all’indirizzo che gli ha fornito tale modulo. Nel nostro esempio presentato sopra, tale indirizzo è [http://localhost/mvcform1]. Il browser effettuerà quindi una richiesta [POST /mvcform1?action=validation] al server [localhost].

Sono stati aggiunti dei pulsanti per consentire all’utente di deselezionare gli elementi delle liste [lstSimple] e [lstMultiple]:

Image

Ciò si traduce nel seguente codice HTML:


                    <td>
                        <select size="3" name="lstSimple">
                            <option value="1" selected>liste1</option>
                            <option value="2">liste2</option>
                            <option value="3">liste3</option>
                            <option value="4">liste4</option>
                            <option value="5">liste5</option>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
                    </td>
....
                    <td>
                        <select multiple size="3" name="lstMultiple">
                            <option value="1" selected>multiple1</option>
                            <option value="2">multiple2</option>
                            <option value="3" selected>multiple3</option>
                            <option value="4">multiple4</option>
                            <option value="5">multiple5</option>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
                    </td>

Cliccando su un pulsante [Raz] si deseleziona qualsiasi elemento dell'elenco a cui è associato. Prendiamo ad esempio l'elenco [lstMultiple]. Cliccando sul pulsante corrispondente [Raz], viene eseguita la funzione JavaScript [raz(lstMultiple)]. Ricordiamo che il codice JavaScript di un documento HTML visualizzato da un browser viene eseguito dallo stesso browser e non dal server. JavaScript è un linguaggio molto completo che consente di conferire un aspetto dinamico alle pagine senza l’intervento del server. La funzione [raz] è la seguente:

        function raz(liste){
            liste.selectedIndex=-1
        }

Questa funzione riceve un parametro che è un oggetto JavaScript che rappresenta un elenco HTML. Questo oggetto possiede proprietà e metodi. Una delle sue proprietà è [selectedIndex], il cui valore è il numero della prima opzione selezionata nell’elenco HTML. Se non ce n’è nessuna, questa proprietà assume il valore -1. Viceversa, assegnare un valore a questa proprietà equivale a selezionare un nuovo elemento nell’elenco HTML, mentre assegnargli il valore -1 equivale a non avere alcun elemento selezionato. È proprio ciò che viene fatto in questo caso.

Si noti infine che il codice di presentazione [formulaire.aspx] non è accompagnato da un controller [formulaire.aspx.vb]. Infatti, nel documento HTML non vi è alcuna parte dinamica generata dal server, quindi non è necessario disporre di un controller.

5.4.4. Elaborazione dell’azione di convalida

Quando il controller elabora l’azione «validazione», deve generare una pagina che elenchi i valori inseriti dall’utente. È compito della pagina [validation.aspx] svolgere questa funzione. Visivamente, la pagina si presenta come segue:

Image

Il suo codice HTML è il seguente:


<%@ Page src="validation.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="validation" %>
<HTML>
    <HEAD>
        <title>validation</title>
    </HEAD>
    <body>
        <P>Valeurs saisies</P>
        <HR width="100%" SIZE="1">
        <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="300" border="1">
            <TR>
                <TD width="84">rdMarie</TD>
                <TD><% =rdMarie%></TD>
            </TR>
            <TR>
                <TD width="84">C1</TD>
                <TD><%=C1%></TD>
            </TR>
            <TR>
                <TD width="84">C2</TD>
                <TD><%=C2%></TD>
            </TR>
            <TR>
                <TD width="84">C3</TD>
                <TD><%=C3%></TD>
            </TR>
            <TR>
                <TD width="84">txtSaisie</TD>
                <TD><%=txtSaisie%></TD>
            </TR>
            <TR>
                <TD width="84">txtMdp</TD>
                <TD><%=txtMdp%></TD>
            </TR>
            <TR>
                <TD width="84">areaSaisie</TD>
                <TD><%=areaSaisie%></TD>
            </TR>
            <TR>
                <TD width="84">cmbValeurs</TD>
                <TD><%=cmbValeurs%></TD>
            </TR>
            <TR>
                <TD width="84">lstSimple</TD>
                <TD><%=lstSimple%></TD>
            </TR>
            <TR>
                <TD width="84">lstMultiple</TD>
                <TD><%=lstMultiple%></TD>
            </TR>
            <TR>
                <TD width="84">secret</TD>
                <TD><%=secret%></TD>
            </TR>
        </TABLE>
    </body>
</HTML>

Le parti dinamiche <%=variabile%> del documento vengono calcolate dal controller [validation.aspx.vb] associato:


Imports System.Text.RegularExpressions

Public Class validation
    Inherits System.Web.UI.Page

    Protected rdMarie As String
    Protected C1 As String
    Protected C2 As String
    Protected C3 As String
    Protected txtSaisie As String
    Protected txtMdp As String
    Protected areaSaisie As String
    Protected cmbValeurs As String
    Protected lstSimple As String
    Protected lstMultiple As String
    Protected secret As String
    Protected delimiteur As New Regex("\r\n")

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'si recuperano i parametri inviati
        rdMarie = getValue("rdMarie")
        C1 = getValue("C1")
        C2 = getValue("C2")
        C3 = getValue("C3")
        txtSaisie = getValue("txtSaisie")
        txtMdp = getValue("txtMdp")
        areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
        cmbValeurs = getValue("cmbValeurs")
        lstSimple = getValue("lstSimple")
        lstMultiple = getValue("lstMultiple")
        secret = getValue("secret")
    End Sub

    Private Function getValue(ByVal champ As String) As String
        ' recupera il valore del campo [champ] dalla richiesta inviata
        ' qualcosa?
        If Request.Form(champ) Is Nothing Then Return ""
        ' si recuperano i valori del campo
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function

End Class

Il calcolo dei valori da visualizzare viene effettuato nella procedura [Form_Load]. Il valore di un campo "inviato" viene ottenuto tramite la funzione getValue(C), dove C è il nome del campo. I punti chiave di questa funzione sono i seguenti:

  • se C non è presente nella stringa di parametri inviata, allora si restituisce la stringa vuota come valore di C
  • altrimenti si ottiene l’array dei valori del campo C tramite [Request.Form.GetValues(C)]. Questi vengono concatenati in una stringa di caratteri nella forma [val1][val2]...[valn], dove [vali] è il valore n. i del campo C

Il campo [areaSaisie] viene trattato in modo particolare. Il suo valore viene inviato dal browser nella forma areaSaisie=riga1\r\nriga2\r\n... dove \r è il carattere con codice ASCII 13 (ritorno a capo) e \n il carattere con codice ASCII 10 (salto di riga). La funzione getValue(areaSaisie) è quindi la stringa "riga1\r\nriga2\r\n...". Questa stringa viene suddivisa in righe dal metodo [Regex.Split]. Si ottiene così un array di stringhe {riga1,riga2,...}. Questo array viene trasformato nella stringa "riga1,riga2,..." dal metodo [String.Join]. È quest'ultima stringa che verrà visualizzata come valore del campo [areaSaisie]. Lo scopo era quello di mostrare come ottenere le diverse righe di un campo HTML di tipo [TextArea].

5.4.5. Test

Inseriamo tutti i file (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) in una cartella <application-path>. Avviamo il server Cassini con i parametri (<application-path>,/mvcform1). Creiamo nella cartella <application-path> un file vuoto denominato [default.aspx], quindi richiediamo l’URL [http://localhost/mvcform1]. Poiché [/mvcform1] è il percorso virtuale di una cartella e non di un documento, il server web visualizzerà il documento [default.aspx], se presente. Ecco perché lo abbiamo creato. Prima di visualizzarlo, verrà eseguito lo script [global.asax], che alla fine farà visualizzare la pagina [formulaire.aspx]. Ecco perché il file [default.aspx] può essere vuoto.

Supponiamo che il modulo convalidato sia il seguente:

Image

L'utilizzo del pulsante [Envoyer] restituisce la seguente pagina:

Image

Notiamo innanzitutto l’URL della risposta: [http://localhost/mvcform1/?action=validation]. Si tratta del valore URL dell’attributo [action] del tag <form> del modulo [formulaire.aspx]:


        <form name="formulaire" method="post" action="?action=validation">

Esaminiamo uno per uno i valori ottenuti per i diversi campi del modulo:

campo
valore
HTML
commenti
rdMarie
<input type="radio" value="sì"
name="rdMarie">
<input type="radio" checked
value="no" name="rdMarie">No
il valore ottenuto è l'attributo [value] del pulsante selezionato
C1
un
<input type="checkbox"
value="uno" name="C1">1
idem
C2
due
<input type="checkbox"
checked value="due" name="C2">2
idem
C3
 
<input type="checkbox"
value="tre" name="C3">3
questo pulsante non è stato selezionato dall'utente. Il suo valore non è stato quindi inviato dal browser. Nel codice, la condizione [Request.Form("C3") is Nothing] è risultata quindi vera.
txtSaisie
Programmazione
asp.net
<input type="text"
... name="txtSaisie">
il valore ottenuto è il testo presente nel campo di immissione al momento della convalida
txtMdp
mdp
<input type="password"
...name="txtMdp">
idem
areaSaisie
le basi della
programmazione web
<textarea name="areaSaisie">
...</textarea>
idem
cmbValeurs
3
<select name="cmbValeurs">
...
<option value="3">scelta3</option>
</select>
il valore ottenuto è l'attributo [value] dell'opzione selezionata
lstSimple
3
<select size="3" name="lstSimple">
....
<option value="3">lista3</option>
...
</select>
idem
lstMultiple
2 4
<select multiple size="3" name="lstMultiple">
...
<option value="2">multiple2
</option>
...
<option value="4">multiple4
</option>
...
</select>
i valori ottenuti corrispondono agli attributi [value] delle opzioni selezionate
segreto
uneValeur
<input type="hidden"
name="secret" value="unValore">
il valore ottenuto è l'attributo [value] del campo nascosto

Ora concentriamoci sugli elenchi. Supponiamo che al momento della convalida lo stato del modulo sia il seguente:

Image

  • l'opzione [choix1] è selezionata nel comboBox
  • nessuna opzione è selezionata negli altri due elenchi. Per ottenere questo risultato sono stati utilizzati i pulsanti [Raz].

Ecco la pagina restituita dopo la convalida:

Image

Quando non viene selezionato alcun valore in un elenco, il browser non invia alcun parametro relativo a tale elenco. Nel codice di [validation.aspx.vb], le espressioni [Request.Form("lstSimple")] e [Request.Form("lstMultiple")] sono quindi uguali alla costante [Nothing], da cui deriva il risultato visualizzato sopra.

5.5. Mantenere lo stato di una pagina

5.5.1. Mantenere lo stato di una pagina con una sessione

Duplichiamo l'intera applicazione precedente in una nuova cartella. Aggiungiamo un link nella pagina QZXW2HTMLP001742ZQ che consenta all'utente di tornare al modulo:

Image

La modifica da apportare alla pagina [validation.aspx] consiste nell’aggiungere il link:


.....
            <TR>
                <TD width="84">secret</TD>
                <TD><%=secret%></TD>
            </TR>
        </TABLE>
        <P>
            <a href="?action=formulaire">Retour au formulaire</a>
        </P>
    </body>
</HTML>

L'attributo [href] del link ha come valore un URL con un unico parametro, [action=formulaire], che consente al server di sapere che deve visualizzare il modulo così com'era al momento della convalida. C'è quindi una differenza rispetto all'azione [init], che visualizza un modulo predefinito. L'URL con parametro [?action=formulaire], infatti, non ha un URL. Questo sarà quindi lo stesso che ha permesso la visualizzazione della pagina di convalida. Se ricordiamo lo studio precedente, questa è l’URL della cartella dell’applicazione. La richiesta passerà quindi attraverso il controller. Quest’ultimo deve ora elaborare l’azione [formulaire]. Il codice di [global.asax.vb] viene modificato come segue:


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' si recupera l'azione da eseguire
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' si esegue l'azione
        Select Case action
            Case "init"
                Server.Transfer("formulaire.aspx", False)
            Case "validation"
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                Server.Transfer("formulaire.aspx", True)
            Case Else
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub

Nel caso in cui l'azione sia "modulo", ci si limita a inoltrare la richiesta alla pagina [formulaire.aspx]. Sappiamo che questa pagina visualizza un modulo predefinito in cui non vi sono parti variabili. Pertanto, questa pagina non può visualizzare il modulo con i valori che aveva al momento della convalida. In questa sede si intende mettere in evidenza questo aspetto. Se tutti i file dell’applicazione sono stati collocati in <application-path>, avviamo Cassini con i parametri (<application-path>,/mvcform2) e poi richiediamo l’URL [http://localhost/mvcform2]. Otteniamo la seguente pagina (vista parziale):

Image

Compiliamo il modulo come segue e poi lo inviamo:

Image

Otteniamo la seguente pagina di conferma:

Image

Utilizziamo il link [Retour au formulaire] presente (ma non visualizzato) nella pagina sopra riportata. Otteniamo la seguente risposta dal server:

Image

Notiamo che:

  • l'URL richiesto contiene effettivamente il parametro action=form, come desiderato
  • il modulo visualizzato ha perso i valori inseriti.

Sappiamo perché non ritroviamo i valori inseriti. Se esaminiamo il codice del documento [formulaire.aspx], notiamo che è tutto statico e che, di conseguenza, è costretto a visualizzare ogni volta la stessa pagina. È evidente che dobbiamo rendere dinamico questo codice. Dovrà visualizzare i valori convalidati dall’utente. Ma dove memorizzarli?

Ricordiamo la regola d’oro del protocollo stateless HTTP:

  • viene richiesta l’URL [http://localhost/mvcform2] – viene ricevuta una risposta. Una connessione TCP-IP è stata aperta tra il client e il server all’inizio della richiesta e chiusa al termine della risposta.
  • L'utente inserisce e conferma i dati. Viene richiesta l'URL [http://localhost/mvcform2/?action=validation] - viene ricevuta una risposta. Una nuova connessione TCP-IP è stata aperta e poi chiusa tra i due partner.
  • L'utente utilizza il link [Retour au formulaire]. Viene richiesta l'URL [http://localhost/mvcform2/?action=formulaire] e viene ricevuta una risposta. Una nuova connessione TCP-IP è stata nuovamente aperta e poi chiusa tra i due partner.

I cicli richiesta-risposta sono indipendenti l’uno dall’altro poiché ciascuno di essi utilizza una nuova connessione TCP-IP. Quando un'applicazione client-server utilizza un'unica connessione TCP-IP per una serie di scambi, il server può identificare un client tramite la sua connessione. Può quindi memorizzare informazioni che assocerà a una connessione specifica e tenere così traccia degli scambi. Quando gli scambi avvengono su connessioni diverse, il server non può identificare un client in base a una connessione. È necessario un altro metodo. Ne abbiamo presentato uno nel capitolo precedente: il meccanismo della sessione. Esso consente ai cicli richiesta-risposta di memorizzare informazioni in un oggetto [Session] accessibile a tutti i cicli successivi.

Ora che disponiamo di un’applicazione MVC con sessione, non possiamo più utilizzare il file [global.asax] come controller, come illustrato nel capitolo precedente. Il ruolo di controller dell’applicazione deve essere svolto da una pagina specifica dedicata a tale scopo. In questo caso, sarà la pagina [main.aspx]. Procederemo come segue:

  • quando l’utente convaliderà i propri dati (azione=convalida), il controller [main.aspx.vb] li memorizzerà nella sessione corrente prima di visualizzare la pagina di convalida.
  • quando sarà necessario visualizzare il modulo con i valori inseriti (azione=modulo), il controller [main.aspx.vb] li recupererà dalla sessione e li inserirà nel contesto prima di visualizzare il modulo.

5.5.2. Il nuovo controller dell’applicazione

Il controller dell'applicazione è costituito dai due file [main.aspx, main.aspx.vb]:

[main.aspx]

<%@ Page src="main.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="main" %>

[main.aspx.vb]


Imports System.Collections.Specialized
Imports Microsoft.VisualBasic

Public Class main
    Inherits System.Web.UI.Page

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' si recupera l'azione da eseguire
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' si esegue l'azione
        Select Case action
            Case "init"
                ' si visualizza il modulo precompilato
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
            Case "validation"
                ' si visualizza la pagina di conferma dopo aver salvato i valori inviati nella sessione
                Session.Item("formulaire") = Request.Form
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                ' si visualizza il modulo con i valori prelevati dalla sessione
                Context.Items("formulaire") = Session.Item("formulaire")
                Server.Transfer("formulaire.aspx", True)
            Case Else
                ' viene visualizzato il modulo precompilato
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub

    Private Function initForm() As NameValueCollection
        ' si inizializza il modulo
        Dim form As New NameValueCollection
        form.Set("rdMarie", "non")
        form.Set("C2", "deux")
        form.Set("txtSaisie", "qqs mots")
        form.Set("txtMdp", "ceciestsecret")
        form.Set("areasaisie", "ligne1" + ControlChars.CrLf + "ligne2" + ControlChars.CrLf)
        form.Set("cmbValeurs", "2")
        form.Set("lstSimple", "1")
        form.Set("lstMultiple", "1")
        form.Add("lstMultiple", "3")
        Return form
    End Function
End Class

Si ritrova l'essenza della struttura del controller dell'applicazione esaminata in precedenza, con le seguenti differenze:

  • il controller opera all’interno della procedura [Form_Load]
  • nel caso dell'azione [validation], i valori del modulo presenti in [Request.Form] vengono memorizzati nella sessione associata alla chiave "modulo". Successivamente l'esecuzione viene trasferita alla pagina [validation.aspx] che visualizzerà tali valori.
  • Per le altre azioni, l’esecuzione viene trasferita in ogni caso alla pagina [formulaire.aspx]. Quest’ultima si aspetta nel proprio contesto una chiave “formulario” che sarà associata a un oggetto del tipo [Request.form], c.a.d o del tipo [NameValueCollection]. Tale oggetto deve contenere la raccolta dei valori dei campi del modulo.
  • nel caso in cui l’azione sia [init] o un’azione non riconosciuta, la raccolta dei valori viene costruita arbitrariamente dalla funzione [initForm].
  • nel caso in cui l'azione sia [formulaire], tale raccolta è la raccolta [Request.Form] che era stata inserita nella sessione dall'azione [validation]

5.5.3. Il nuovo modulo

Poiché l’applicazione non visualizza più lo stesso contenuto nel modulo, quest’ultimo deve essere generato dinamicamente. La nuova pagina [formulaire.aspx] diventa la seguente:


<%@ Page src="formulaire.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire" %>
<HTML>
    <HEAD>
        <title>Formulaire</title>
        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        function raz(liste){
            liste.selectedIndex=-1
        }
        </script>
    </HEAD>
    <body>
        <p>
            Gestion d'un formulaire
        </p>
        <hr>
        <form name="formulaire" method="post" action="main.aspx?action=validation">
            <table border="1">
                <tr>
                    <td>
                        Etes-vous marié(e)</td>
                    <td>
                        <p align="center">
                            <INPUT type="radio" value="oui" name="rdMarie" <%=rdouichecked%>>Oui
                         <INPUT type="radio" value="non" name="rdMarie" <%=rdnonchecked%>>Non
                        </p>
                    </td>
                </tr>
                <TR>
                    <TD>Cases à cocher
                    </TD>
                    <TD>
                        <P align="center">
                            <INPUT type="checkbox" value="un" name="C1" <%=c1checked%>>1
                             <INPUT type="checkbox" value="deux" name="C2" <%=c2checked%>>2
                            <INPUT type="checkbox" value="trois" name="C3" <%=c3checked%>>3
                        </P>
                    </TD>
                </TR>
                <TR>
                    <TD>Champ de saisie</TD>
                    <TD>
                        <P align="center">
                            <INPUT type="text" maxLength="30" value="<%=txtSaisie%>" name="txtSaisie">
                        </P>
                    </TD>
                </TR>
                <tr>
                    <td>
                        Mot de passe</td>
                    <td>
                        <p align="center">
                            <input type="password" maxlength="12" size="12" value="<%=txtMdp%>" name="txtMdp">
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Boîte de saisie</td>
                    <td>
                        <textarea name="areaSaisie"><%=areaSaisie%></textarea>
                    </td>
                </tr>
                <tr>
                    <td>
                        ComboBox</td>
                    <td>
                        <select name="cmbValeurs">
                            <%=cmbValeursOptions%>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        Liste à choix simple</td>
                    <td>
                        <select size="3" name="lstSimple">
                            <%=lstSimpleOptions%>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazSimple" onclick="raz(lstSimple)">
                    </td>
                </tr>
                <tr>
                    <td>
                        Liste à choix multiple</td>
                    <td>
                        <select multiple size="3" name="lstMultiple">
                            <%=lstMultipleOptions%>
                        </select>
                        <INPUT type="button" value="Raz" name="btnRazMultiple" onclick="raz(lstMultiple)">
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton simple</td>
                    <td>
                        <p align="center">
                            <input onclick="effacer()" type="button" value="Effacer" name="btnEffacer">
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton submit</td>
                    <td>
                        <p align="center">
                            <input type="submit" value="Envoyer" name="btnEnvoyer">
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>
                        Bouton reset</td>
                    <td>
                        <p align="center">
                            <input type="reset" value="Rétablir" name="btnRetablir" runat="server">
                        </p>
                    </td>
                </tr>
            </table>
            <input type="hidden" name="secret" value="uneValeur">
        </form>
    </body>
</HTML>

Commentiamo le variabili dinamiche che compaiono nel codice HTML:

variabile
ruolo
rdouichecked
avrà il valore "checked" se il pulsante di opzione [oui] deve essere selezionato, altrimenti il valore ""
rdnonchecked
lo stesso vale per il pulsante di opzione [non]
c1checked
lo stesso vale per la casella di controllo [C1]
c2checked
lo stesso vale per la casella di controllo [C2]
c3checked
lo stesso vale per la casella di selezione [C3]
txtSaisie
il testo da inserire nel campo [txtSaisie]
txtMdp
il testo da inserire nel campo [txtMdp]
areaSaisie
il testo da inserire nel campo [areaSaisie]
cmbValeursOptions
il testo HTML delle opzioni dell'elenco a discesa [cmbValeurs]
lstSimpleOptions
il testo HTML delle opzioni dell'elenco a discesa [lstSimple]
lstMultipleOptions
il testo HTML delle opzioni dell'elenco a discesa [lstMultiple]
  

I valori di queste variabili vengono calcolati dal controller della pagina [formulaire.aspx.vb]:


Imports Microsoft.VisualBasic
Imports System.Collections.Specialized

Public Class formulaire
    Inherits System.Web.UI.Page

    ' campi fissi del modulo
    Private libellésCmbValeurs() As String = {"choix1", "choix2", "choix3"}
    Private valeursCmbValeurs() As String = {"1", "2", "3"}
    Private libellésLstSimple() As String = {"liste1", "liste2", "liste3"}
    Private valeursLstSimple() As String = {"1", "2", "3"}
    Private libellésLstMultiple() As String = {"multiple1", "multiple2", "multiple3", "multiple4", "multiple5"}
    Private valeursLstMultiple() As String = {"1", "2", "3", "4", "5"}

    ' campi dinamici del modulo
    Protected rdouichecked As String
    Protected rdnonchecked As String
    Protected c1checked As String
    Protected c2checked As String
    Protected c3checked As String
    Protected txtSaisie As String
    Protected txtMdp As String
    Protected areaSaisie As String
    Protected cmbValeursOptions As String
    Protected lstSimpleOptions As String
    Protected lstMultipleOptions As String

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' si recupera la richiesta precedente dalla sessione
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If
        ' si prepara la pagina da visualizzare
        ' pulsanti di opzione
        rdouichecked = ""
        rdnonchecked = "checked"
        If isEqual(form("rdMarie"), "oui") Then
            rdouichecked = "checked"
            rdnonchecked = ""
        End If
        ' caselle di controllo
        c1checked = ""
        If isEqual(form("C1"), "un") Then c1checked = "checked"
        c2checked = ""
        If isEqual(form("C2"), "deux") Then c2checked = "checked"
        c3checked = ""
        If isEqual(form("C3"), "trois") Then c3checked = "checked"
        ' campi di immissione
        txtSaisie = ""
        If Not form("txtSaisie") Is Nothing Then txtSaisie = form("txtSaisie").ToString
        txtMdp = ""
        If Not form("txtMdp") Is Nothing Then txtMdp = form("txtMdp").ToString
        areaSaisie = ""
        If Not form("areaSaisie") Is Nothing Then areaSaisie = form("areaSaisie").ToString
        ' elenchi
        Dim sélections() As String = {}
        If Not form("cmbValeurs") Is Nothing Then sélections = form.GetValues("cmbValeurs")
        cmbValeursOptions = getOptions(valeursCmbValeurs, libellésCmbValeurs, sélections)
        sélections = New String() {}
        If Not form("lstSimple") Is Nothing Then sélections = form.GetValues("lstSimple")
        lstSimpleOptions = getOptions(valeursLstSimple, libellésLstSimple, sélections)
        sélections = New String() {}
        If Not form("lstMultiple") Is Nothing Then sélections = form.GetValues("lstMultiple")
        lstMultipleOptions = getOptions(valeursLstMultiple, libellésLstMultiple, sélections)
    End Sub

    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
        ' restituisce il codice HTML delle opzioni di un tag <select>
        ' valori: tabella dei valori delle opzioni del tag
        ' etichette: tabella delle etichette delle opzioni del tag
        ' selezioni: opzioni da selezionare
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' si scorre l'elenco dei valori delle opzioni
        For iValeur = 0 To valeurs.Length - 1
            ' si verifica se il valore corrente deve essere selezionato
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' si inserisce il codice HTML dell'opzione
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' si restituisce il risultato
        Return toString
    End Function

    Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
        ' restituisce vero se il campo è uguale al valore
        If champ Is Nothing OrElse champ.ToString <> valeur Then
            Return false
        Else
            Return true
        End If
    end function
End Class

Quando la pagina [formulaire.aspx] inizia a essere eseguita, individua nel proprio contesto una chiave "modulo" associata alla raccolta di valori dei campi che deve visualizzare.


         ' si recupera la query precedente dalla sessione
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If

Ci si potrebbe chiedere perché si verifichi l'esistenza di [Context.Items("formulaire")]. Infatti, il controller assegna un valore a questo oggetto in ogni caso. Tuttavia, nulla impedisce al client di richiedere direttamente la pagina [formulaire.aspx] senza passare attraverso il controller. Se ciò dovesse accadere, il codice precedente opererà con una collezione di valori vuota, ma non si verificherà alcun "arresto anomalo".

Il codice esplora la collezione di valori ricevuti per calcolare tutte le variabili dinamiche della pagina HTML ad essa associata. Sebbene sia lungo, questo codice non è particolarmente complicato e lasciamo al lettore il compito di approfondirlo per non appesantire questa spiegazione. Ci soffermeremo tuttavia sul modo in cui viene generato il codice HTML dalle tre liste di tipo [select]. Questo codice viene generato dalla seguente funzione:

    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
         ' restituisce il codice HTML delle opzioni di un tag <select>
         ' valori: array dei valori delle opzioni del tag
         ' etichette: tabella delle etichette delle opzioni del tag
         ' selezioni: opzioni da selezionare
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
         ' si scorre l'elenco dei valori delle opzioni
        For iValeur = 0 To valeurs.Length - 1
             ' si verifica se il valore corrente deve essere selezionato
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
             ' si inserisce il codice HTML dell'opzione
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
         ' si restituisce il risultato
        Return toString
    End Function

Ricordiamo che le opzioni di un tag <select> corrispondono al seguente codice HTML:

<option [selected] value="...">texte</option>

Per ogni opzione, occorre quindi generare tre informazioni:

  • il valore dell'opzione nell'attributo [value]
  • il testo dell’opzione tra i tag <option> e </option>
  • la parola chiave [selected] se l’opzione deve essere selezionata nell’elenco

Per generare queste tre informazioni per ciascuna delle opzioni, la funzione [getOptions] riceve tre valori:

  1. l'array dei valori delle opzioni in [valeurs]
  2. l'array dei testi delle opzioni in [libelles]
  3. l'array dei valori da selezionare in [sélections]

5.5.4. La pagina di convalida

La pagina di convalida rimane invariata:

[validation.aspx]


<%@ Page src="validation.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="validation" %>
<HTML>
    <HEAD>
        <title>validation</title>
    </HEAD>
    <body>
        <P>Valeurs saisies</P>
        <HR width="100%" SIZE="1">
        <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="300" border="1">
            <TR>
                <TD width="84">rdMarie</TD>
                <TD><% =rdMarie%></TD>
            </TR>
            <TR>
                <TD width="84">C1</TD>
                <TD><%=C1%></TD>
            </TR>
            <TR>
                <TD width="84">C2</TD>
                <TD><%=C2%></TD>
            </TR>
            <TR>
                <TD width="84">C3</TD>
                <TD><%=C3%></TD>
            </TR>
            <TR>
                <TD width="84">txtSaisie</TD>
                <TD><%=txtSaisie%></TD>
            </TR>
            <TR>
                <TD width="84">txtMdp</TD>
                <TD><%=txtMdp%></TD>
            </TR>
            <TR>
                <TD width="84">areaSaisie</TD>
                <TD><%=areaSaisie%></TD>
            </TR>
            <TR>
                <TD width="84">cmbValeurs</TD>
                <TD><%=cmbValeurs%></TD>
            </TR>
            <TR>
                <TD width="84">lstSimple</TD>
                <TD><%=lstSimple%></TD>
            </TR>
            <TR>
                <TD width="84">lstMultiple</TD>
                <TD><%=lstMultiple%></TD>
            </TR>
            <TR>
                <TD width="84">secret</TD>
                <TD><%=secret%></TD>
            </TR>
        </TABLE>
        <P>
            <a href="main.aspx?action=formulaire">Retour au formulaire</a>
        </P>
    </body>
</HTML>

[validation.aspx.vb]


Imports Microsoft.VisualBasic
Imports System.Text.RegularExpressions

Public Class validation
    Inherits System.Web.UI.Page

    Protected rdMarie As String
    Protected C1 As String
    Protected C2 As String
    Protected C3 As String
    Protected txtSaisie As String
    Protected txtMdp As String
    Protected areaSaisie As String
    Protected cmbValeurs As String
    Protected lstSimple As String
    Protected lstMultiple As String
    Protected secret As String
    Protected delimiteur As New Regex("\r\n")

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'si recuperano i parametri inviati
        rdMarie = getValue("rdMarie")
        C1 = getValue("C1")
        C2 = getValue("C2")
        C3 = getValue("C3")
        txtSaisie = getValue("txtSaisie")
        txtMdp = getValue("txtMdp")
        areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
        cmbValeurs = getValue("cmbValeurs")
        lstSimple = getValue("lstSimple")
        lstMultiple = getValue("lstMultiple")
        secret = getValue("secret")
        ' li si salva nella sessione
        'Session("modulo") = Request.Form
    End Sub

    Private Function getValue(ByVal champ As String) As String
        ' recupera il valore del campo [champ] dalla richiesta inviata via POST
        ' qualcosa?
        If Request.Form(champ) Is Nothing Then Return ""
        ' si recuperano i valori del campo
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function
End Class

5.5.5. I test

I file [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] vengono inseriti in <application-path> e Casini viene avviato con i parametri (<application-path>,/mvcform3). Successivamente, richiediamo l'URL [http://localhost/mvcform3/main.aspx]. Otteniamo il modulo pre-inizializzato:

Image

Compiliamo il modulo come segue:

Image

Utilizziamo il pulsante [Envoyer] riportato sopra. Otteniamo la seguente risposta dal server:

Image

Utilizziamo il link [Retour au formulaire] riportato sopra per tornare al modulo. Otteniamo la seguente nuova risposta:

Image

Il modulo appare esattamente come lo avevamo inviato.

5.5.6. Conclusione

L'esempio precedente ci ha mostrato che è possibile mantenere lo stato di una pagina nel corso dei cicli di richiesta-risposta tra il client e il server. Tuttavia, questo lavoro non è banale. Vedremo in un capitolo successivo che con ASP.NET è possibile lasciare che sia il server a ripristinare autonomamente lo stato di una pagina.