Skip to content

5. Gestione dell'interfaccia utente

5.1. Introduzione

Nella relazione client-server sul web, il client invia informazioni al server sotto forma di una stringa di parametri [param1=val1&param2=val2&...]. Nei nostri esempi precedenti, abbiamo spesso creato questa stringa manualmente richiedendo URL del tipo [http://localhost/appli? param1=val1&param2=val2&...]. In realtà, le informazioni che il client invia al server provengono dai moduli compilati dall'utente. In questo capitolo vedremo come creare questi moduli. Introdurremo inoltre lo strumento WebMatrix, che ci consentirà di progettare interfacce utente. L'installazione di questo strumento è descritta nelle appendici.

5.2. Il linguaggio HTML

5.2.1. Un esempio

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

  • una tabella
  • un'immagine
  • un link

Image

Avvia [WebMatrix] e seleziona l'opzione [File/Nuovo file]:

Image

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

Image

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

Image

Per inserire un elemento da questa tavolozza, è sufficiente fare doppio clic su di esso e poi posizionarlo nella finestra [Design]. La modalità [HTML] consente di costruire il documento HTML utilizzando un editor di testo. Ciò richiede la conoscenza della sintassi HTML. Nella scheda [HTML] è stato generato uno scheletro di documento:

Image

La finestra [HTML] è molto utile per chi non ha familiarità con l'HTML. Si crea il documento nella finestra [Design] e si controlla il codice HTML generato nella finestra [HTML]. In questo modo, si acquisisce gradualmente padronanza dell'HTML e si può lavorare rapidamente utilizzando esclusivamente l'editor di testo, senza ricorrere alla modalità [Design]. Ora mostreremo come creare il documento HTML presentato all'inizio di questa sezione. Stiamo lavorando nella finestra [Design]. Per prima cosa, inseriamo direttamente la prima riga di testo:

Image

  • aggiungiamo il componente [Linea orizzontale] dalla tavolozza dei componenti:

Image

  • aggiungiamo il componente [Tabella]:

Image

  • posizioniamo il cursore sulla terza riga della tabella per eliminarla utilizzando l'opzione [HTML/Modifica tabella/Elimina riga tabella]. Quindi inseriamo il testo previsto in ciascuna cella:

Image

  • posizioniamo il cursore in una delle celle della tabella ed esaminiamo le sue proprietà. La finestra delle proprietà viene visualizzata in basso a destra dell'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 contenente la cella. Facciamo clic sull'elenco a discesa (clicca per vedere gli elementi HTML padre) in alto per selezionare l'oggetto <TABLE>:

Image

  • L'oggetto <TABLE> ha una proprietà [border] che imposta la larghezza del bordo che circonda le celle della tabella. Qui, impostiamo border=1.

Image

  • Ora modificheremo gli attributi dell'oggetto <TD> nella cella (1,2) per impostare align=Center e width=200 (pixel). Il testo sarà centrato nella cella (align=center) e la cella avrà una larghezza di 200 pixel. Per vedere la modifica, 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 [immagine] nella 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 [qui] in un link all'URL [http://istia.univ-angers.fr]. Per farlo, lo selezioniamo e poi scegliamo l'opzione [HTML/Inserisci collegamento ipertestuale]:

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>

Abbiamo ancora alcuni dettagli da sistemare. Innanzitutto, vorremmo dare un titolo al nostro documento. [WebMatrix] non consente di farlo in modalità [Design]. Nella scheda [HTML], sostituiamo la sezione <head>..</head> con quanto segue:

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

Inoltre, vorremmo che il testo [HTML - 1] apparisse con caratteri più grandi. Il tag <Hi>text</Hi> consente di impostare la dimensione del testo, con "i" che va da 1 a 6, dal più grande al più piccolo. Qui useremo H2. Il tag

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

diventa:

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

La finestra [Design] riflette le nostre modifiche:

Image

Non resta che testarla utilizzando l'opzione [View/Start] o [F5]. [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 quali parametri sono stati utilizzati per avviare [Cassini]:

Image

Abbiamo illustrato le nozioni di base sulla creazione di una pagina HTML con [WebMatrix]. Invitiamo i lettori a creare altre pagine HTML e a controllare ogni volta il codice HTML generato. A poco a poco, saranno in grado di creare una pagina senza utilizzare la modalità [Design]. Un documento HTML presenta generalmente la seguente struttura:

<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>: questa è la parte non visualizzabile del documento. Fornisce informazioni al browser che visualizzerà il documento. Spesso contiene il tag <title>...</title>, che imposta il testo che apparirà nella barra del titolo del browser. Può contenere anche altri tag, compresi quelli che definiscono le parole chiave del documento, che vengono poi utilizzate dai motori di ricerca. Questa sezione può contenere anche script, solitamente scritti in JavaScript o VBScript, che verranno eseguiti dal browser.

<attributi del body>...</body>: Questa è la sezione che verrà visualizzata dal browser. I tag HTML contenuti in questa sezione indicano al browser il layout visivo "desiderato" per il documento. Ogni browser interpreta questi tag a modo suo. Di conseguenza, due browser potrebbero visualizzare lo stesso documento web in modo diverso. Questa è generalmente una delle sfide che devono affrontare i 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>
HTML
Tag HTML ed esempi
titolo del documento
<title>HTML1</title>
HTML1 apparirà nella barra del titolo del browser quando il documento viene visualizzato
barra orizzontale
<horizontal> : visualizza una linea orizzontale
tabella
<attributi tabella>....</table> : per definire la tabella
<tr attributi>... : per definire una riga
<td attributi>... : per definire una cella
esempi:
<table border="1">...: l'attributo border definisce lo spessore del bordo della tabella
<td align="center" width="200">cell(1,2) : definisce una cella il cui contenuto sarà cell(1,2). Questo contenuto sarà centrato orizzontalmente (align="center"). La cella avrà una larghezza di 200 pixel (width="200")
immagine
<img src="univ01.gif" />: definisce un'immagine il cui file sorgente è univ01.gif sul server web (src="univ01.gif"). Questo collegamento si trova in un documento web accessibile tramite l'URL http://localhost/exemple1.htm. Pertanto, il browser richiederà l'URL http://localhost/univ01.gif per recuperare l'immagine a cui si fa riferimento qui.
link
<a href="http://istia.univ-angers.fr">qui: fa sì che il testo "qui" funga da collegamento all'URL http://istia.univ-angers.fr.

In questo semplice esempio, possiamo vedere che per costruire l'intero documento, il browser deve effettuare due richieste al server:

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

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

5.2.2. Creazione di un modulo

Lo scopo di un modulo HTML è quello di presentare all'utente una pagina di immissione dati simile ai moduli di immissione presenti in Windows. Il modulo di immissione viene inviato al browser come documento HTML. Il browser visualizza il modulo all'utente, che lo compila e lo invia utilizzando un pulsante con quella funzione. Il browser trasmette quindi i valori inseriti al server per l'elaborazione. Vedremo che non invia l'intero modulo al server, ma solo i valori inseriti. L'esempio seguente mostra 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>

La mappatura tra elementi visivi e tag HTML è la seguente:

Controllo visivo
Tag HTML
form
<form name="form" method="post">
campo di immissione
<input type="text" maxlength="30" value="a few words" name="txtInput" />
campo di input nascosto
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" />
campo di immissione multilinea
<textarea name="inputArea">riga1
riga2</textarea>
pulsanti di opzione
<input type="radio" value="yes" name="rdMarie" />
<input type="radio" checked value="no" name="rdMarie" />No
caselle di controllo
<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
Menu a tendina
<select name="cmbValeurs">
<option value="1">opzione1</option>
<option value="2" selected>opzione2</option>
<option value="3">opzione3</option>
</select>
elenco a selezione singola
<select size="3" name="lstSimple">
<option value="1" selected>elenco1</option>
<option value="2">elenco2</option>
<option value="3">elenco3</option>
<option value="4">elenco4</option>
<option value="5">elenco5</option>
</select>
elenco a selezione multipla
<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>
campo nascosto
<input type="hidden" name="secret" value="aValue" />
pulsante di invio
<input type="submit" value="Invia" name="submitButton" />
pulsante di reset
<input type="reset" value="Reset" name="btnReset" runat="server" />
pulsante
<input onclick="clear()" type="button" value="Cancella" name="btnClear" />

Esaminiamo questi diversi controlli.

5.2.2.1. Il

modulo
<form name="form" method="post">
HTML
<form name="..." method="..." action="...">...</form>
attributi
name="formexample": nome del modulo
method="..." : metodo utilizzato dal browser per inviare i valori raccolti nel modulo al server web
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"). Ciò vale per tutti i controlli presenti all'interno di un modulo. Questo 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 inserite dall'utente tramite la tastiera o il mouse e inviarle a un URL di un server web. Quale? Quello a cui fa riferimento l'attributo action="URL". Se questo attributo manca, le informazioni saranno inviate all'URL del documento in cui si trova il modulo. In che modo un client web invia le informazioni (i dati contenuti nel modulo) a un server web? Ne abbiamo parlato in dettaglio. Può utilizzare due metodi diversi chiamati POST e GET. L'attributo method="method" del tag <form>, dove method è impostato su GET o POST, indica al browser quale metodo 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

campo di immissione
<input type="text" maxlength="30" value="alcune parole" name="txtInput" />
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" />
Tag HTML
<input type="..." name="..." size=".." value="..">
Il tag input esiste per vari controlli. È l'attributo type che distingue questi diversi controlli l'uno dall'altro.
attributi
type="text": specifica che si tratta di un campo di immissione testo
type="password": i caratteri nel campo di immissione vengono sostituiti da asterischi (*). Questa è l'unica differenza rispetto a un normale campo di immissione. Questo tipo di controllo è adatto per l'immissione di password.
size="12": numero di caratteri visibili nel campo — non impedisce l'inserimento di più caratteri
maxlength="30": imposta il numero massimo di caratteri a 30 — il browser è responsabile dell'applicazione di questo attributo
name="txtInput": nome del controllo
value="alcune parole": testo che verrà visualizzato nel campo di immissione.

5.2.2.3. Campo di immissione multilinea

Image

campo di immissione multilinea
<textarea name="inputArea">riga1
riga2</textarea>
Tag HTML
<textarea ...>testo</textarea>
visualizza un campo di immissione multilinea con testo iniziale all'interno
attributi
rows="2": numero di righe
cols="'20": numero di colonne
name="areaSaisie": nome del controllo

5.2.2.4. Pulsanti di opzione

Image

pulsanti di opzione
<input type="radio" value="yes" name="rdMarie" />
<input type="radio" checked value="no" name="rdMarie" />No
Tag HTML
<input type="radio" attribute2="value2" ..../>testo
visualizza un pulsante di opzione con del testo accanto.
attributi
name="rdMarie": nome del controllo. I pulsanti di opzione con lo stesso nome formano un gruppo di pulsanti mutuamente esclusivi: solo uno di essi può essere selezionato.
value="value": valore assegnato al pulsante di opzione. Non confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Il testo 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

caselle di controllo
<input type="checkbox" value="one" name="C1" />1
<input type="checkbox" checked value="due" name="C2" />2
<input type="checkbox" value="tre" name="C3" />3

Image

Tag HTML
<input type="checkbox" attribute2="value2" ..../>testo
visualizza una casella di controllo con del testo accanto.
attributi
name="C1": nome del controllo. Le caselle di controllo possono avere o meno lo stesso nome. Le caselle di controllo con lo stesso nome formano un gruppo di caselle di controllo associate.
value="value": valore assegnato alla casella di controllo. Non confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Il testo serve solo a scopo di 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="cmbValues">
<option value="1">scelta1</option>
<option value="2" selected>opzione2</option>
<option value="3">Opzione 3</option>
</select>

Image

Tag HTML
<select size=".." name="..">
<option [selected="selected"] [value="value"]>testo</option>
...
</select>
visualizza il testo tra i tag <option>...</option> in un elenco
attributi
name="cmbValues": nome del controllo.
size="1": numero di voci visibili dell'elenco. size="1" rende l'elenco equivalente a una casella combinata. Questo è il valore predefinito se l'attributo [size] è assente.
selected="selected": se questo attributo è presente per una voce dell'elenco, tale voce appare selezionata nell'elenco. Nel nostro esempio sopra, la voce dell'elenco "choice2" appare come voce selezionata nella casella combinata quando viene visualizzata per la prima volta.
value="value": imposta il valore da inviare al server se la voce viene selezionata. Se questo attributo è assente, al server viene inviato il testo associato all'opzione.

5.2.2.7. Elenco a selezione singola

elenco a selezione singola
<select size="3" name="lstSimple">
<option value="1" selected>list1</option>
<option value="2">list2</option>
<option value="3">elenco3</option>
<option value="4">elenco4</option>
<option value="5">elenco5</option>
</select>

Image

Tag HTML
<select size=".." name="..">
<option [selected] [value="value"]>...</option>
...
</select>
visualizza il testo tra i tag <option>...</option> in un elenco
attributi
gli stessi dell'elenco a discesa che visualizza un solo elemento. Questo controllo differisce dal precedente elenco a discesa solo per l'attributo size>1.

5.2.2.8. Elenco a selezione multipla

elenco a selezione multipla
<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

Tag HTML
<select size=".." name=".." multiple>
<option [selected] ] [value="value"]>...</option>
...
</select>
visualizza il testo tra i tag <option>...</option> in un elenco
attributi
multiple: consente la selezione di più elementi nell'elenco. Nell'esempio sopra, gli elementi list1 e list3 sono entrambi selezionati.

5.2.2.9. Pulsante

pulsante
<input onclick="clear()" type="button" value="Cancella" name="btnClear" />

Image

Tag HTML
<input type="button" value="..." name="..." onclick="clear()" ....>
attributi
type="button": definisce un controllo pulsante. Esistono altri due tipi di pulsanti: submit e reset.
value="Cancella": il testo visualizzato sul pulsante
onclick="function()": 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 sopra riportata è sintassi JavaScript. Se gli script sono scritti in VBScript, si scriverebbe onclick="function" senza le parentesi. La sintassi rimane la stessa se è necessario passare dei parametri alla funzione: onclick="function(val1, val2,...)"
Nel nostro esempio, cliccando sul pulsante "Cancella" viene chiamata la seguente funzione JavaScript:

        <script language="javascript">
        funzione clear(){
            alert("Hai cliccato sul pulsante [Cancella]");
        }
        </script>
La funzione clear visualizza un messaggio:

5.2.2.10. Pulsante Invia

Pulsante Invia
<input type="submit" value="Invia" name="btnSubmit" />

Image

Tag HTML
<input type="submit" value="Invia" name="btnSend">
attributi
type="submit": definisce il pulsante come pulsante per l'invio dei dati del modulo al server web. Quando l'utente fa clic su questo pulsante, il browser invierà i dati del modulo all'URL definito nell'attributo action del tag <form>, utilizzando il metodo definito dall'attributo method dello stesso tag.
value="Invia": il testo visualizzato sul pulsante

5.2.2.11. Pulsante di reset

pulsante di ripristino
<input type="reset" value="Reset" name="btnReset" runat="server" />

Image

Tag HTML
<input type="reset" value="Reset" name="btnReset">
attributi
type="reset": definisce il pulsante come pulsante di reset del modulo. Quando l'utente fa clic su questo pulsante, il browser ripristinerà il modulo allo stato in cui è stato ricevuto.
value="Reset": il testo visualizzato sul pulsante

5.2.2.12. Campo nascosto

campo nascosto
<input type="hidden" name="secret" value="aValue" />
Tag HTML
<input type="hidden" name="..." value="...">
attributi
type="hidden": specifica che si tratta di un campo nascosto. Un campo nascosto fa parte del modulo ma non viene visualizzato all'utente. Tuttavia, se l'utente chiedesse 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="aValue": valore del campo nascosto.
Qual è lo scopo del campo nascosto? Consente al server web di conservare le informazioni tra le richieste di un client. Si consideri un'applicazione di shopping online. Il client acquista un articolo iniziale art1 in quantità q1 sulla prima pagina di un catalogo e poi passa a una nuova pagina del catalogo. Per ricordare che il client ha acquistato q1 articoli di art1, il server può inserire queste due informazioni in un campo nascosto nel modulo web della nuova pagina. In questa nuova pagina, il cliente acquista q2 unità dell'articolo art2. Quando i dati di questo secondo modulo vengono inviati al server, il server non solo riceverà le informazioni (q2,art2) ma anche (q1,art1), che fanno anch'esse parte del modulo come campo nascosto che non può essere modificato dall'utente. Il server web inserirà quindi le informazioni (q1,art1) e (q2,art2) in un nuovo campo nascosto e invierà una nuova pagina del catalogo. E così via.

5.3. Invio dei valori del modulo a un server web tramite un browser

Sappiamo già, dal capitolo precedente, come un client trasmette le informazioni al server. Lo fa tramite:

  • una richiesta HTTP GET: url?param1=va1&param2=val2&....
  • una richiesta HTTP POST 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 impostato su GET o POST. Questo è ciò che dimostreremo ora. La pagina che abbiamo esaminato in precedenza è una pagina statica. Per accedere alle intestazioni HTTP inviate dal browser che richiede questo documento, la convertiremo in una pagina dinamica per un server web .NET (IIS o Cassini). Il codice statico precedente viene inserito in un file denominato [form_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 [form_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
        ' saves the current query in request.txt of the page folder
        Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
        Me.Request.SaveAs(requestFileName, True)
    End Sub
End Class

Ogni volta che viene richiamato il documento [form_get.aspx], la richiesta del client verrà salvata in un file [request.txt] dalla procedura Page_Init. Abbiamo già incontrato questa modalità di funzionamento, quindi non commenteremo ulteriormente il controller.

5.3.1. Metodo GET

Eseguiamo un test iniziale, in cui 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 è stata registrata 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 avviene sempre quando l'URL viene fornito dall'utente. Compiliamo il modulo come segue:

Image

Utilizziamo il pulsante [Invia] qui sopra. Il suo codice HTML è il seguente:

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

Quando si fa clic sul pulsante [Invia], il browser invia i parametri del modulo (il tag <form>) all'URL specificato nell'attributo [action] del tag <form action="URL">, se presente. Se questo attributo non esiste, i parametri del modulo vengono inviati all'URL che ha fornito il modulo. È il caso in questione. Il pulsante [Invia] dovrebbe quindi attivare una richiesta dal browser all'URL [http://localhost/form2/formulaire_get.aspx] con i parametri del modulo inclusi. Poiché la pagina [formulaire_get.aspx] memorizza la richiesta ricevuta, dovremmo essere in grado di vedere come il client ha inviato questi parametri. Proviamo. Facciamo clic sul pulsante [Invia]. Riceviamo la seguente risposta dal browser:

Image

Questa è la pagina iniziale, ma si può notare che l'URL è cambiato nel campo [Indirizzo] del browser. È diventato il seguente:

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

Possiamo vedere che le scelte effettuate nel modulo si riflettono nell'URL. Diamo un'occhiata al 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 tratta di una richiesta HTTP molto simile a quella inviata inizialmente dal browser quando ha richiesto il documento senza passare alcun parametro. Ci sono due differenze:

GET HTTP/1.1 URL
I parametri del modulo sono stati aggiunti all'URL del documento nel formato ?param1=val1&param2=val2&...
Referer
Il client utilizza questa intestazione HTTP per indicare l'URL del documento che stava visualizzando quando ha effettuato la richiesta

Diamo un'occhiata più da vicino a come sono stati passati i parametri nella richiesta GET URL?param1=value1&param2=value2&... HTTP/1.1, dove i parametri sono i nomi dei controlli del modulo web e i valori sono quelli ad essi associati. Di seguito è riportata una tabella a tre colonne:

  • Colonna 1: mostra la definizione di un controllo HTML dall'esempio
  • Colonna 2: mostra come questo controllo appare in un browser
  • Colonna 3: mostra il valore inviato al server dal browser per il controllo nella Colonna 1 nella forma che assume nella richiesta GET dell'esempio
Controllo HTML
Visualizzazione pre-convalida
Valori restituiti
<input type="radio" value="yes" name="rdMarie" />Sì
<input type="radio" checked
value="no" name="rdMarie" />No
- 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 di controllo
selezionate dall'utente
<input type="text" maxlength="30" value="alcune
parole" name="txtInput" />
txtSaisie=programmazione+asp.net
- testo digitato dall'utente nel
. Gli spazi sono stati sostituiti
con il segno +
<input type="password"
maxlength="12" size="12"
value="aPassword"
name="txtMdp" />
txtMdp="thisIsSecret"
- testo digitato dall'utente nel
. Il testo effettivamente digitato era
"thisIsSecret". L'ultimo carattere è andato
perduto perché l'attributo
maxlength="12" ha limitato il numero di
a 12.
<textarea name="areaSaisie">
riga1
riga2</textarea>
areaSaisie=le+nozioni+di+base+di+
la%0D%0A
programmazione+web
- testo digitato dall'utente nel
. %OD%OA è il
. Gli spazi sono stati
sostituiti con il segno +
<select name="cmbValeurs">
<option value="1">scelta1
</option>
<option value="2" selected>opzione2
</option>
<option value="3">opzione3
</option>
</select>
cmbValues=3
- valore selezionato dall'utente dall'
elenco a selezione singola
<select size="3"
name="lstSimple">
<option value="1"
selected>list1</option>
<option value="2">elenco2
</option>
<option value="3">elenco3
</option>
<option value="4">elenco4
</option>
<option value="5">elenco5
</option>
</select>
lstSimple=3
- valore selezionato dall'utente dall'
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
elenco a selezione multipla
<input type="submit"
value="Invia"
name="btnSubmit" />
btnEnvoyer=Invia
- attributi name e value del pulsante utilizzato
sono stati utilizzati per inviare i dati del modulo
al server
<input type="hidden"
name="secret"
value="aValue" />
 
secret=aValue
- attributo value del campo nascosto

Potresti chiederti cosa abbia fatto il server con i parametri che gli sono stati passati. In realtà, nulla. Una volta ricevuta la richiesta

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 passato i parametri all'URL nel documento [http://localhost/form2/formulaire_get.aspx], ovvero al documento che abbiamo creato inizialmente. Non abbiamo scritto alcun codice per recuperare ed elaborare i parametri che il client ci invia. Quindi tutto avviene come se la richiesta del client fosse semplicemente:

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

Ecco perché, in risposta al nostro pulsante [Submit], abbiamo ricevuto la stessa pagina ottenuta inizialmente richiedendo l'URL [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. Per farlo, copiamo il file [form_get.aspx] in [form_post.aspx] e modifichiamo solo il tag <form> in [form_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 modificare il controller [form_get.aspx.vb], quindi lo lasciamo così com'è. Richiediamo il nuovo documento tramite l'URL [http://localhost/form2/formulaire_post.aspx], compiliamo il modulo come abbiamo fatto per il metodo GET e inviamo i parametri al server utilizzando il pulsante [Submit]. Riceviamo la seguente pagina di risposta dal server:

Image

Otteniamo quindi lo stesso risultato del metodo GET, ovvero la pagina iniziale. Notiamo una differenza: nel campo [Indirizzo] del browser, i parametri trasmessi non compaiono. Ora, diamo un'occhiata alla richiesta inviata dal client e salvata 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 client compaiono nuovi elementi:

POST HTTP/1.1
La richiesta GET è stata sostituita da una richiesta POST. I parametri non sono più presenti nella prima riga della richiesta. Possiamo notare che ora sono posizionati dopo la richiesta HTTP, a seguito di una riga vuota. La loro codifica è identica a quella della richiesta GET.
Content-Length
numero di caratteri "pubblicati", ovvero il numero di caratteri che il server web deve leggere dopo aver ricevuto le intestazioni HTTP per recuperare il documento inviato dal client. Il documento in questione qui è 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. Un metodo è migliore dell'altro? Abbiamo visto che se i valori di un modulo fossero inviati dal browser utilizzando il metodo GET, il browser visualizzerebbe l'URL richiesto nel campo Indirizzo nel formato URL?param1=val1&param2=val2&.... Questo può essere visto sia come un vantaggio che come uno svantaggio:

  • un vantaggio se si desidera consentire all'utente di salvare questo URL parametrizzato nei propri segnalibri
  • uno svantaggio se non si desidera che l'utente abbia accesso a determinate informazioni del modulo, come i campi nascosti

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

5.4. Elaborazione lato server dei valori dei moduli

5.4.1. Panoramica dell'esempio

Ora che abbiamo stabilito la connessione 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. Il capitolo precedente ha fornito la risposta:

  • se il metodo del tag <form> è GET, i valori dei parametri verranno recuperati dalla collezione [Request.QueryString]
  • Se il metodo del tag <form> è POST, i valori dei parametri "inviati" verranno recuperati dalla collezione [Request.Form]. A questo punto è necessario un chiarimento. Il tag <form> può specificare l'URL di destinazione per la richiesta GET o POST utilizzando l'attributo [action]. Questo URL può essere configurato indipendentemente dal fatto che si tratti di una richiesta GET o POST, nella forma action="url?param1=val1&param2=val2&..". Questi parametri vengono quindi aggiunti a quelli contenuti tra i tag <form> e </form>, che saranno inviati al server tramite una richiesta GET o POST. Poiché fanno parte dell'URL di destinazione, saranno recuperati dalla raccolta [Request.QueryString] indipendentemente dal fatto che la richiesta sia di tipo GET o POST.

Ora scriveremo un'applicazione MVC con due viste:

  • La prima vista è il modulo precedente. La chiameremo [form_view].
  • La seconda vista è una pagina informativa che elenca i valori inseriti nella prima pagina. Un link permette all'utente di tornare al modulo. Chiameremo questa vista [view_confirmation].

La [form_view] viene inviata all'utente, che la compila e la invia. Potrebbe apparire così appena prima dell'invio:

Image

L'utente fa clic sul pulsante [Invia] per inviare i propri dati. In cambio, riceve la seguente [validation_view]:

Image

5.4.2. Il controller dell'applicazione

Nel capitolo precedente abbiamo visto che possiamo assegnare il ruolo di controller per un'applicazione MVC al file [global.asax], attraverso il quale passano tutte le richieste dei client. Abbiamo già presentato un'applicazione MVC costruita in questo modo e qui seguiremo il modello di sviluppo presentato in precedenza. Il file [global.asax] sarà il seguente:

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

Consiste in una singola riga che fa riferimento al controller situato 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)
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        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 controller funziona come segue:

  • cerca una stringa di parametri contenente il parametro [action] nell'URL di destinazione. Se questo manca, si comporta come se [action=init] fosse presente nella stringa di parametri.
  • Sono riconosciute solo due azioni:
    • init: il modulo precompilato viene inviato al client
    • validation: la pagina di conferma dei dati inseriti dall'utente viene inviata al client
  • Se l'azione non è una di quelle sopra indicate, il sistema si comporta come se fosse presente [action=init]. Potrebbe anche essere restituita 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] eseguire questa operazione. 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>

Vediamo il codice HTML del modulo che abbiamo 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 si fa clic sul pulsante [Invia] verranno inviati utilizzando il metodo HTTP POST
  • action: la sintassi action="url" viene utilizzata per specificare 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&... Questo è ciò che viene fatto qui, dove 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 ha fornito questo modulo. Nel nostro esempio sopra, questo indirizzo è [http://localhost/mvcform1]. Il browser effettuerà quindi una richiesta [POST /mvcform1?action=validation] alla macchina [localhost].

Sono stati aggiunti dei pulsanti per consentire all'utente di deselezionare gli elementi dagli elenchi [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 sul pulsante [Cancella] si deseleziona tutti gli elementi dell'elenco a cui è associato. Prendiamo l'esempio dell'elenco [lstMultiple]. Cliccando sul pulsante [Cancella] corrispondente si attiva l'esecuzione della funzione JavaScript [raz(lstMultiple)]. Ricordate che il codice JavaScript in un documento HTML visualizzato da un browser viene eseguito dal browser stesso, non dal server. JavaScript è un linguaggio molto completo che permette di aggiungere funzionalità dinamiche alle pagine senza l'intervento del server. La funzione [raz] è la seguente:

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

Questa funzione accetta un parametro che è un oggetto JavaScript che rappresenta un elenco HTML. Questo oggetto ha 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à è -1. Al contrario, impostare un valore per questa proprietà seleziona un nuovo elemento nell'elenco HTML, e impostarlo a -1 significa che nessun elemento è selezionato. Questo è ciò che viene fatto qui.

Infine, si noti che il codice di presentazione [form.aspx] non è accompagnato da un controller [form.aspx.vb]. Infatti, non vi è alcun contenuto dinamico generato dal server nel documento HTML, quindi non è necessario un controller.

5.4.4. Gestione dell'azione di convalida

Quando il controller elabora l'azione "validation", deve generare una pagina che elenchi i valori inseriti dall'utente. È compito della pagina [validation.aspx] eseguire questa operazione. Visivamente, la pagina ha questo aspetto:

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 <%=variable%> del documento vengono calcolate dal controller associato [validation.aspx.vb]:


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
        'retrieve posted parameters
        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
        ' retrieves the value of field [field] from the posted request
        ' anything?
        If Request.Form(champ) Is Nothing Then Return ""
        ' retrieve the value(s) of the
        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 eseguito nella procedura [Form_Load]. Il valore di un campo "pubblicato" viene ottenuto utilizzando 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 dei parametri inviati, viene restituita la stringa vuota come valore di C
  • altrimenti, l'array di valori per il campo C viene ottenuto tramite [Request.Form.GetValues(C)]. Questi vengono concatenati in una stringa nella forma [val1][val2]...[valn], dove [vali] è l'i-esimo valore del campo C

Il campo [areaSaisie] viene gestito in modo speciale. Il suo valore viene inviato dal browser nella forma areaSaisie=line1\r\nline2\r\n... dove \r è il codice ASCII 13 (ritorno a capo) e \n è il codice ASCII 10 (avanzamento riga). La funzione getValue(areaSaisie) è quindi la stringa "line1\r\nline2\r\n...". Questa stringa viene suddivisa in righe utilizzando il metodo [Regex.Split]. Ciò produce un array di stringhe {line1,line2,...}. Questo array viene convertito nella stringa "line1,line2,..." utilizzando il metodo [String.Join]. È questa stringa finale che verrà visualizzata come valore del campo [areaSaisie]. L'obiettivo era quello di dimostrare come estrarre le singole righe da un campo HTML [TextArea].

5.4.5. Test

Mettiamo tutti i file (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) in una cartella chiamata <application-path>. Avviamo il server Cassini con i parametri (<application-path>,/mvcform1). Creiamo un file [default.aspx] vuoto nella cartella <application-path>, 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 esiste. Ecco perché lo abbiamo creato. Prima di visualizzarlo, verrà eseguito lo script [global.asax] che alla fine visualizzerà la pagina [form.aspx]. Questo è il motivo per cui il file [default.aspx] può essere vuoto.

Supponiamo che il modulo convalidato sia il seguente:

Image

Facendo clic sul pulsante [Invia] viene visualizzata la pagina seguente:

Image

Innanzitutto, si noti l'URL di risposta: [http://localhost/mvcform1/?action=validation]. Questo è l'URL dell'attributo [action] del tag <form> nel 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" selected
value="no" name="rdMarie">No
Il valore ottenuto è l'attributo [value] della casella di controllo
C1
a
<input type="checkbox"
value="uno" name="C1">1
uguale
C2
due
<input type="checkbox"
selezionato value="due" name="C2">2
uguale
C3
 
<input type="checkbox"
value="three" 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] era quindi vera.
txtInput
Programmazione
ASP.NET
<input type="text"
... name="txtSaisie">
Il valore restituito è il testo presente nel campo di immissione al momento della convalida
txtMdp
password
<input type="password"
...name="txtMdp">
same
campo di immissione
le basi della
programmazione web
<textarea name="areaSaisie">
...</textarea>
stesso
cmbValues
3
<select name="cmbValues">
...
<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">list3</option>
...
</select>
stesso
lstMultiple
2 4
<select multiple size="3" name="lstMultiple">
...
<option value="2">multiple2
</option>
...
<option value="4">multiple4
</option>
...
</select>
I valori ottenuti sono quelli degli attributi [value] delle opzioni selezionate
segreto
aValue
<input type="hidden"
name="secret" value="aValue">
Il valore ottenuto è l'attributo [value] del campo nascosto

Ora diamo un'occhiata agli elenchi. Supponiamo che al momento della convalida lo stato del modulo sia il seguente:

Image

  • l'opzione [choice1] è selezionata nella casella combinata
  • nessuna opzione è selezionata negli altri due elenchi. Abbiamo utilizzato i pulsanti [Clear] per ottenere questo risultato.

Ecco la pagina restituita dopo la convalida:

Image

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

5.5. Mantenimento dello stato di una pagina

5.5.1. Mantenimento dello stato di una pagina con una sessione

Duplichiamo l'intera applicazione precedente in una nuova cartella. Aggiungiamo un collegamento alla pagina [validation.aspx] che consente all'utente di tornare al modulo:

Image

La modifica da apportare alla pagina [validation.aspx] consiste nell'aggiunta del collegamento:


.....
            <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=form], che permette al server di sapere che deve visualizzare il modulo così com'era al momento dell'invio. Ciò differisce dall'azione [init], che visualizza un modulo predefinito. L'URL con il parametro [?action=form] non ha in realtà un URL. Sarà quindi lo stesso di quello che ha visualizzato la pagina di invio. Come abbiamo visto nell'esempio precedente, questo è l'URL della cartella dell'applicazione. La richiesta passerà quindi attraverso il controller. Il controller deve ora gestire l'azione [form]. Il codice in [global.asax.vb] viene modificato come segue:


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        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

Se l'azione è "form", inoltriamo semplicemente la richiesta alla pagina [form.aspx]. Sappiamo che questa pagina visualizza un modulo predefinito senza parti variabili. Pertanto, questa pagina non può visualizzare il modulo con i valori che aveva al momento dell'invio. Stiamo cercando di evidenziare questo punto qui. Se tutti i file dell'applicazione sono stati inseriti in <application-path>, avviamo Cassini con i parametri (<application-path>,/mvcform2) e quindi 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 [Torna al modulo] presente (ma non mostrato) nella pagina sopra. Riceviamo la seguente risposta dal server:

Image

Notiamo che:

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

Sappiamo perché non riusciamo a recuperare i valori inseriti. Se guardiamo il codice del documento [form.aspx], vediamo che è tutto statico, quindi è costretto a visualizzare la stessa pagina ogni volta. È chiaro che dobbiamo rendere questo codice dinamico. Deve visualizzare i valori convalidati dall'utente. Ma dove dovremmo memorizzarli?

Ricordiamo la legge ferrea del protocollo HTTP stateless:

  • Viene richiesta l'URL [http://localhost/mvcform2] e si riceve una risposta. Una connessione TCP-IP è stata aperta tra il client e il server all'inizio della richiesta e chiusa alla fine della risposta.
  • L'utente inserisce e invia i dati. Viene richiesto l'URL [http://localhost/mvcform2/?action=validation] e si riceve una risposta. Viene aperta e poi chiusa una nuova connessione TCP/IP tra le due parti.
  • L'utente fa clic sul collegamento [Torna al modulo]. Viene richiesto l'URL [http://localhost/mvcform2/?action=formulaire] e viene ricevuta una risposta. È stata aperta e poi chiusa una nuova connessione TCP/IP tra le due parti.

I cicli di richiesta-risposta sono indipendenti l'uno dall'altro perché ciascuno utilizza una nuova connessione TCP-IP. Quando un'applicazione client-server utilizza una singola connessione TCP-IP per una serie di scambi, il server può identificare un client tramite la sua connessione. Può quindi memorizzare informazioni che collegherà a una connessione specifica e tracciare così gli scambi. Quando gli scambi avvengono su connessioni diverse, il server non può identificare un client tramite una connessione. È necessario un altro metodo. Abbiamo introdotto uno di questi metodi nel capitolo precedente: il meccanismo di sessione. Esso consente ai cicli di richiesta-risposta di memorizzare informazioni in un oggetto [Session] accessibile a tutti i cicli successivi.

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

  • Quando l'utente invia i propri dati (action=validation), il controller [main.aspx.vb] li memorizzerà nella sessione corrente prima di visualizzare la pagina di convalida.
  • Quando il modulo deve essere visualizzato con i valori inseriti (action=form), 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 da 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
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        Select Case action
            Case "init"
                ' the pre-filled form is displayed
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
            Case "validation"
                ' the confirmation page is displayed after saving the values posted in the session
                Session.Item("formulaire") = Request.Form
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                ' displays the form with values taken from the session
                Context.Items("formulaire") = Session.Item("formulaire")
                Server.Transfer("formulaire.aspx", True)
            Case Else
                ' the pre-filled form is displayed
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub
 
    Private Function initForm() As NameValueCollection
        ' initialize the form
        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

Vediamo l'essenza della struttura del controller dell'applicazione discussa in precedenza, con le seguenti differenze:

  • il lavoro del controller viene eseguito nella procedura [Form_Load]
  • nel caso dell'azione [validation], i valori del modulo presenti in [Request.Form] vengono memorizzati nella sessione associata alla chiave "form". L'esecuzione viene quindi trasferita alla pagina [validation.aspx], che visualizzerà questi valori.
  • Per le altre azioni, l'esecuzione viene trasferita in tutti i casi alla pagina [formulaire.aspx]. Questa pagina si aspetta una chiave "formulaire" nel proprio contesto, che sarà associata a un oggetto di tipo [Request.Form], ovvero di tipo [NameValueCollection]. Questo oggetto deve contenere la raccolta dei valori per i campi del modulo.
  • Se l'azione è [init] o un'azione non riconosciuta, la raccolta di valori viene costruita arbitrariamente dalla funzione [initForm].
  • Se l'azione è [form], questa raccolta è la raccolta [Request.Form] che è stata inserita nella sessione dall'azione [validation]

5.5.3. Il nuovo modulo

Poiché l'applicazione non visualizza più lo stesso contenuto nel modulo, questo deve essere generato dinamicamente. La nuova pagina [form.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 [yes] deve essere selezionato, altrimenti il valore ""
rdnonchecked
lo stesso vale per il pulsante di opzione [no]
c1checked
lo stesso vale per la casella di controllo [C1]
c2checked
lo stesso per la casella di controllo [C2]
c3checked
lo stesso per la casella di controllo [C3]
txtInput
il testo da inserire nel campo [txtInput]
txtPassword
il testo da inserire nel campo [txtPassword]
areaInput
il testo da inserire nel campo [areaInput]
cmbOptionValues
il testo HTML per le opzioni nell'elenco a discesa [cmbValeurs]
lstSimpleOptions
il testo HTML delle opzioni nell'elenco a discesa [lstSimple]
lstMultipleOptions
il testo HTML delle opzioni nell'elenco a discesa [lstMultiple]
  

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


Imports Microsoft.VisualBasic
Imports System.Collections.Specialized
 
Public Class formulaire
    Inherits System.Web.UI.Page
 
    ' constant form fields
    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"}
 
    ' dynamic form fields
    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
        ' retrieve the previous request from the session
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If
        ' prepare the page to be displayed
        ' radio buttons
        rdouichecked = ""
        rdnonchecked = "checked"
        If isEqual(form("rdMarie"), "oui") Then
            rdouichecked = "checked"
            rdnonchecked = ""
        End If
        ' checkboxes
        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"
        ' input fields
        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
        ' lists
        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
        ' renders HTML code for <select> tag options
        ' values: table of tag option values
        ' labels: table of tag option labels
        ' selections: options to select
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' browse the list of option values
        For iValeur = 0 To valeurs.Length - 1
            ' check whether the current value should be selected
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' we integrate the HTML code from the
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' we return the result
        Return toString
    End Function
 
    Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
        ' returns true if field is equal to value
        If champ Is Nothing OrElse champ.ToString <> valeur Then
            Return false
        Else
            Return true
        End If
    end function
End Class

Quando la pagina [form.aspx] inizia a essere eseguita, troverà nel proprio contesto una chiave "form" associata alla raccolta dei valori dei campi che deve visualizzare.


        ' retrieve the previous request from the session
        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é controlliamo se [Context.Items("form")] esiste. In realtà, il controller assegna un valore a questo oggetto in tutti i casi. Tuttavia, nulla impedisce al client di richiedere direttamente la pagina [form.aspx] senza passare attraverso il controller. Se così fosse, il codice precedente funzionerebbe con una raccolta di valori vuota, ma non ci sarebbe alcun "crash".

Il codice esegue un'iterazione attraverso la raccolta di valori ricevuta per calcolare tutte le variabili dinamiche della pagina HTML associata. Sebbene sia lungo, questo codice non è particolarmente complicato e lasceremo al lettore il compito di esplorarlo per non appesantire questa spiegazione. Ci concentreremo, tuttavia, su come generare il codice HTML per i tre elenchi [select]. Questo codice è generato dalla seguente funzione:

    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
        ' renders HTML code for <select> tag options
        ' values: table of tag option values
        ' labels: table of tag option labels
        ' selections: options to select
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' browse the list of option values
        For iValeur = 0 To valeurs.Length - 1
            ' check whether the current value should be selected
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' we integrate the HTML code of the
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' we return the result
        Return toString
    End Function

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

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

Per ogni opzione, ci sono quindi tre informazioni da generare:

  • 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 ogni opzione, la funzione [getOptions] riceve tre valori:

  1. l'array dei valori delle opzioni in [values]
  2. l'array dei testi delle opzioni in [labels]
  3. l'array dei valori da selezionare in [selections]

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
        'retrieve posted parameters
        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")
        ' save them in the session
        'Session("formulaire") = Request.Form
    End Sub
 
    Private Function getValue(ByVal champ As String) As String
        ' retrieves the value of field [field] from the posted request
        ' anything?
        If Request.Form(champ) Is Nothing Then Return ""
        ' retrieve the value(s) of the
        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. Test

I file [main.aspx, main.aspx.vb, form.aspx, form.aspx.vb, validation.aspx, validation.aspx.vb] vengono collocati in <percorso-applicazione> e Casini viene avviato con i parametri (<percorso-applicazione>,/mvcform3). Richiediamo quindi l'URL [http://localhost/mvcform3/main.aspx]. Otteniamo il modulo pre-inizializzato:

Image

Compiliamo il modulo come segue:

Image

Facciamo clic sul pulsante [Invia] in alto. Riceviamo la seguente risposta dal server:

Image

Utilizziamo il link [Back to form] in alto per tornare al modulo. Riceviamo la seguente nuova risposta:

Image

Vediamo il modulo esattamente come lo abbiamo inviato.

5.5.6. Conclusione

L'esempio precedente ci ha mostrato che è possibile mantenere lo stato di una pagina durante i cicli di richiesta-risposta tra il client e il server. Tuttavia, non si tratta di un compito banale. Vedremo in un capitolo successivo che con ASP.NET è possibile fare in modo che sia il server stesso a ripristinare lo stato di una pagina.