5. Gestion de l'interface utilisateur
5.1. Introduction
Dans la relation client-serveur du web, le client transmet des informations au serveur sous la forme de chaîne de paramètres [param1=val1¶m2=val2&...]. Nous avons dans nos exemples précédents, construit cette chaîne le plus souvent à la main en demandant des url de la forme [http://localhost/appli? param1=val1¶m2=val2&...]. Dans la réalité, les informations que le transmet le client au serveur proviennent de formulaires que l'utilisateur a remplis. Nous explorons la construction de ceux-ci dans ce chapitre. Nous introduisons également l'outil WebMatrix qui va nous permettre de dessiner les interfaces utilisateur. L'installation de cet outil est présentée dans les annexes.
5.2. Le langage HTML
5.2.1. Un exemple
Considérons l'exemple suivant, créé avec [Web Matrix] qui présente :
- un tableau
- une image
- un lien

Lançons [WebMatrix] puis prenons l'option [File/New File] :

Nous choisissons de créer une page HTML. Les informations ci-dessus vont créer un fichier [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm]. [WebMatrix] offre deux possibilités d'éditer ce fichier : le mode [Design] et le mode [HTML] :

Le mode [Design] permet d'utiliser la palette de composants HTML proposée par [WebMatrix] :

Pour insérer un élément de cette palette, il suffit de double-cliquer dessus et ensuite de le positionner sur la fenêtre [Design]. Le mode [HTML] permet de construire le document HTML à l'aide d'un éditeur de texte. Il faut pour cela connaître la syntaxe du langage HTML. Dans l'onglet [HTML], un squelette de document a été généré :

La fenêtre [HTML] est très utile à celui qui ne connaît pas le langage HTML. Il construit dans la fenêtre [Design] son document et vérifie le code HTML généré dans la fenêtre [HTML]. Il acquiert ainsi progressivement la maîtrise de HTML et peut assez rapidement travailler uniquement avec l'éditeur de texte sans l'aide du mode [Design]. Nous allons montrer maintenant comment construire le document HTML présenté au début de cette section. Nous travaillons dans la fenêtre [Design]. Tout d'abord, nous introduisons directement la première ligne de texte :

- nous ajoutons le composant [Horizontal Rule] dans la palette des composants :

- nous ajoutons le composant [Table] :

- nous plaçons le curseur dans la troisième ligne de la table pour la supprimer avec l'option [HTML/Edit Table/Delete Table Row]. Puis nous inscrivons le texte attendu dans chaque cellule :

- nous plaçons le curseur dans l'une des cellules du tableau et nous nous intéressons aux propriétés de celle-ci. La fenêtre de propriétés est présentée en bas à droite de l'environnement de travail :

- la cellule est représentée par la balise HTML <TD>. On nous présente donc les propriétés de la balise <TD>. Nous nous intéressons au tableau qui est un objet englobant la cellule. Nous cliquons sur la liste déroulante (click to see parent HTML elements) ci-dessus pour sélectionner l'objet <TABLE> :

- l'objet <TABLE> a une propriété [border] fixant la largeur de la bordure entorant les cellules du tableau. Ici, nous prenons border=1.

- nous éditons maintenant les attributs de l'objet <TD> de la cellule (1,2) pour fixer align=Center et width=200 (pixels). Le texte sera centré dans la cellule (align=center) et celle-ci sera large de 200 pixels. Pour voir la modification, vous pouvez parfois être obligé de sélectionner l'onglet [HTML] puis revenir sur l'onglet [Design] :

- maintenant nous plaçons le texte qui le précède l'image :

- puis l'image en double-cliquant sur le composant [image] de la palette :

- nous sélectionnons l'image pour éditer ses propriétés :

- dans l'attribut [src], nous mettons le nom du fichier contenant l'image, ici [univ01.gif] :

- nous plaçons le texte précédant le lien :

- nous faisons du texte [ici] un lien vers l'url [http://istia.univ-angers.fr]. Pour cela, nous le sélectionnons puis prenons l'option [HTML/Insert Hyperlink] :

- nous obtenons le résultat suivant :

- nous y sommes presque. Regardons le code HTML généré dans l'onglet [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>
Il nous reste quelques détails à régler. Tout d'abord nous aimerions donner un titre à notre document. [WebMatrix] ne permet pas de le faire en mode [Design]. Dans l'onglet [HTML] nous remplaçons la séquence <head>..</head> par la séquence suivante :
Par ailleurs, nous souhaiterions avoir le texte [Le langage HTML - 1] en plus grands caractères. La séquence <Hi>texte</Hi> permet de fixer la taille d'un texte avec i variant de 1 à 6 du plus grand au plus petit. Ici, nous prendrons H2. La séquence
devient :
La fenêtre [Design] reflète nos changements :

Il ne nous reste plus qu'à tester à l'aide de l'option [View/Start] ou [F5]. [WebMatrix] demande quelques renseignements pour lancer le serveur Web [Cassini] :

Nous pouvons accepter les valeurs proposées par défaut. Le serveur [Cassini] est lancé et notre page affichée dans un navigateur :

Par curiosité, nous pouvons vérifier avec quels paramètres a été lancé [Cassini] :

Nous avons présenté les bases de construction d'une page HTML avec [WebMatrix]. Le lecteur est invité à construire d'autres pages HTML et à vérifier à chaque fois le code HTML généré. Peu à peu, il sera capable de construire une page sans l'aide du mode [Design]. Un document HTML a la forme générale suivante :
L'ensemble du document est encadré par les balises <html>...</html>. Il est formé de deux parties :
<head>...</head> : c'est la partie non affichable du document. Elle donne des renseignements au navigateur qui va afficher le document. On y trouve souvent la balise <title>...</title> qui fixe le texte qui sera affiché dans la barre de titre du navigateur. On peut y trouver d'autres balises notamment des balises définissant les mots clés du document, mots clés utilisés ensuite par les moteurs de recherche. On peut trouver également dans cette partie des scripts, écrits le plus souvent en javascript ou vbscript et qui seront exécutés par le navigateur.
<body attributs>...</body> : c'est la partie qui sera affichée par le navigateur. Les balises HTML contenues dans cette partie indiquent au navigateur la forme visuelle "souhaitée" pour le document. Chaque navigateur va interpréter ces balises à sa façon. Deux navigateurs peuvent alors visualiser différemment un même document web. C'est généralement l'un des casse-têtes des concepteurs web.
Le code HTML du document précédent était le suivant :
<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>
|
Elément |
balises et exemples HTML |
|
<title>HTML1</title> HTML1 apparaîtra dans la barre de titre du navigateur qui affichera le document |
|
<hr> : affiche un trait horizontal |
|
<table attributs>....</table> : pour définir le tableau <tr attributs>...</tr> : pour définir une ligne <td attributs>...</td> : pour définir une cellule exemples : <table border="1">...</table> : l'attribut border définit l'épaisseur de la bordure du tableau <td align="center" width="200">cellule(1,2)</td> : définit une cellule dont le contenu sera cellule(1,2). Ce contenu sera centré horizontalement (align="center"). La cellule aura une largeur de 200 pixels (width="200") |
|
<img src="univ01.gif" /> : définit une image dont le fichier source est univ01.gif sur le serveur web (src="univ01.gif"). Ce lien se trouve sur un document web obtenu avec l'URL http://localhost/exemple1.htm. Aussi, le navigateur demandera-t-il l'URL http://localhost/univ01.gif pour avoir l'image référencée ici. |
|
<a href="http://istia.univ-angers.fr">ici</a> : fait que le texte ici sert de lien vers l'URL http://istia.univ-angers.fr. |
On voit dans ce simple exemple que pour construire l'intéralité du document, le navigateur doit faire deux requêtes au serveur :
http://localhost/exemple1.htm pour avoir le source HTML du document
http://localhost/univ01.gif pour avoir l'image univ01.gif
5.2.2. Construction d'un formulaire
Un formulaire HTML a pour but de présenter à l'utilisateur une page de saisie d'informations analogue aux formulaire de saisie rencontrés sous windows. Le formulaire de saisie est envoyé sous la forme d'un document HTML au navigateur. Celui-ci va présenter le formulaire à l'utilisateur qui va le remplir et le valider avec un bouton ayant cette fonction. Le navigateur va alors transmettre les valeurs saisies au serveur pour traitement. On verra qu'il ne renvoie pas au serveur la totalité du formulaire mais seulement les valeurs saisies. L'exemple suivant présente un formulaire Web créé lui aussi avec WebMatrix :

Le code HTML généré par [WebMatrix] est le suivant :
<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'association contrôle visuel <--> balise HTML est le suivant :
|
Contrôle |
balise HTML |
|
<form name="formulaire" method="post"> |
|
<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" /> |
|
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> |
|
<textarea name="areaSaisie">ligne1 ligne2</textarea> |
|
<input type="radio" value="oui" name="rdMarie" />Oui <input type="radio" checked value="non" name="rdMarie" />Non |
|
<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 |
|
<select name="cmbValeurs"> <option value="1">choix1</option> <option value="2" selected>choix2</option> <option value="3">choix3</option> </select> |
|
<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> |
|
<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="hidden" name="secret" value="uneValeur" /> |
|
<input type="submit" value="Envoyer" name="btnEnvoyer" /> |
|
<input type="reset" value="Rétablir" name="btnRetablir" runat="server" /> |
|
<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" /> |
Passons en revue ces différents contrôles.
5.2.2.1. Le formulaire
|
<form name="formulaire" method="post"> |
|
<form name="..." method="..." action="...">...</form> |
|
name="frmexemple" : nom du formulaire method="..." : méthode utilisée par le navigateur pour envoyer au serveur web les valeurs récoltées dans le formulaire action="..." : URL à laquelle seront envoyées les valeurs récoltées dans le formulaire. Un formulaire web est entouré des balises <form>...</form>. Le formulaire peut avoir un nom (name="xx"). C'est le cas pour tous les contrôles qu'on peut trouver dans un formulaire. Ce nom est utile si le document web contient des scripts qui doivent référencer des éléments du formulaire. Le but d'un formulaire est de rassembler des informations données par l'utilisateur au clavier/souris et d'envoyer celles-ci à une URL de serveur web. Laquelle ? Celle référencée dans l'attribut action="URL". Si cet attribut est absent, les informations seront envoyées à l'URL du document dans lequel se trouve le formulaire. Comment un client web fait-il pour donner des informations (celles contenues dans le formulaire) à un serveur web ? Nous l'avons vu en détail. Il peut utiliser deux méthodes différentes appelées POST et GET. L'attribut method="méthode", avec méthode égale à GET ou POST, de la balise <form> indique au navigateur la méthode à utiliser pour envoyer les informations recueillies dans le formulaire à l'URL précisée par l'attribut action="URL". Lorsque l'attribut method n'est pas précisé, c'est la méthode GET qui est prise par défaut. |
5.2.2.2. Champ de saisie

|
<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" /> <input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> |
|
<input type="..." name="..." size=".." value=".."> La balise input existe pour divers contrôles. C'est l'attribut type qui permet de différentier ces différents contrôles entre eux. |
|
type="text" : précise que c'est un champ de saisie type="password" : les caractères présents dans le champ de saisie sont remplacés par des caractères *. C'est la seule différence avec le champ de saisie normal. Ce type de contrôle convient pour la saisie des mots de passe. size="12" : nombre de caractères visibles dans le champ - n'empêche pas la saisie de davantage de caractères maxlength="30" : fixe à 30 le nombre maximal de caractères - le navigateur est chargé de faire respecter cet attribut name="txtSaisie" : nom du contrôle value="qqs mots" : texte qui sera affiché dans le champ de saisie. |
5.2.2.3. Champ de saisie multilignes

|
<textarea name="areaSaisie">ligne1 ligne2</textarea> |
|
<textarea ...>texte</textarea> affiche une zone de saisie multilignes avec au départ texte dedans |
|
rows="2" : nombre de lignes cols="'20" : nombre de colonnes name="areaSaisie" : nom du contrôle |
5.2.2.4. Boutons radio

|
<input type="radio" value="oui" name="rdMarie" />Oui <input type="radio" checked value="non" name="rdMarie" />Non |
|
<input type="radio" attribut2="valeur2" ..../>texte affiche un bouton radio avec texte à côté. |
|
name="rdMarie" : nom du contrôle. Les boutons radio portant le même nom forment un groupe de boutons exclusifs les uns des autres : on ne peut cocher que l'un d'eux. value="valeur" : valeur affectée au bouton radio. Il ne faut pas confondre cette valeur avec le texte affiché à côté du bouton radio. Celui-ci n'est destiné qu'à l'affichage. checked : si ce mot clé est présent, le bouton radio est coché, sinon il ne l'est pas. |
5.2.2.5. Cases à cocher
|
<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 |

|
<input type="checkbox" attribut2="valeur2" ..../>texte affiche une case à cocher avec texte à côté. |
|
name="C1" : nom du contrôle. Les cases à cocher peuvent porter ou non le même nom. Les cases portant le même nom forment un groupe de cases associées. value="valeur" : valeur affectée à la case à cocher. Il ne faut pas confondre cette valeur avec le texte affiché à côté du bouton radio. Celui-ci n'est destiné qu'à l'affichage. checked : si ce mot clé est présent, le bouton radio est coché, sinon il ne l'est pas. |
5.2.2.6. Liste déroulante (combo)
|
<select name="cmbValeurs"> <option value="1">choix1</option> <option value="2" selected>choix2</option> <option value="3">choix3</option> </select> |

|
<select size=".." name=".."> <option [selected="selected"] [value="valeur"]>texte</option> ... </select> affiche dans une liste les textes compris entre les balises <option>...</option> |
|
name="cmbValeurs" : nom du contrôle. size="1" : nombre d'éléments de liste visibles. size="1" fait de la liste l'équivalent d'un combobox. C'est la valeur par défaut si l'attribut [size] est absent. selected="selected" : si ce mot clé est présent pour un élément de liste, ce dernier apparaît sélectionné dans la liste. Dans notre exemple ci-dessus, l'élément de liste choix2 apparaît comme l'élément sélectionné du combo lorsque celui-ci est affiché pour la première fois. value="valeur" : fixe la valeur à envoyer au serveur si l'élément est sélectionné. Si cet attribut est absent, c'est alors le texte associé à l'opton qui est envoyé au serveur. |
5.2.2.7. Liste à sélection unique
|
<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> |

|
<select size=".." name=".."> <option [selected] [value="valeur"]>...</option> ... </select> affiche dans une liste les textes compris entre les balises <option>...</option> |
|
les mêmes que pour la liste déroulante n'affichant qu'un élément. Ce contrôle ne diffère de la liste déroulante précédente que par son attribut size>1. |
5.2.2.8. 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> |

|
<select size=".." name=".." multiple> <option [selected] ] [value="valeur"]>...</option> ... </select> affiche dans une liste les textes compris entre les balises <option>...</option> |
|
multiple : permet la sélection de plusieurs éléments dans la liste. Dans l'exemple ci-dessus, les éléments liste1 et liste3 sont tous deux sélectionnés. |
5.2.2.9. Bouton de type button
|
<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" /> |

|
<input type="button" value="..." name="..." onclick="effacer()" ....> |
|
type="button" : définit un contrôle bouton. Il existe deux autres types de bouton, les types submit et reset. value="Effacer" : le texte affiché sur le bouton onclick="fonction()" : permet de définir une fonction à exécuter lorsque l'utilisateur clique sur le bouton. Cette fonction fait partie des scripts définis dans le document web affiché. La syntaxe précédente est une syntaxe javascript. Si les scripts sont écrits en vbscript, il faudrait écrire onclick="fonction" sans les parenthèses. La syntaxe devient identique s'il faut passer des paramètres à la fonction : onclick="fonction(val1, val2,...)" Dans notre exemple, un clic sur le bouton Effacer appelle la fonction javascript effacer suivante : La fonction effacer affiche un message :
|
5.2.2.10. Bouton de type submit
|
<input type="submit" value="Envoyer" name="btnEnvoyer" /> |

|
<input type="submit" value="Envoyer" name="btnEnvoyer"> |
|
type="submit" : définit le bouton comme un bouton d'envoi des données du formulaire au serveur web. Lorsque le client va cliquer sur ce bouton, le navigateur va envoyer les données du formulaire à l'URL définie dans l'attribut action de la balise <form> selon la méthode définie par l'attribut method de cette même balise. value="Envoyer" : le texte affiché sur le bouton |
5.2.2.11. Bouton de type reset
|
<input type="reset" value="Rétablir" name="btnRetablir" runat="server" /> |

|
<input type="reset" value="Rétablir" name=" btnRetablir "> |
|
type="reset" : définit le bouton comme un bouton de réinitialisation du formulaire. Lorsque le client va cliquer sur ce bouton, le navigateur va remettre le formulaire dans l'état où il l'a reçu. value="Rétablir" : le texte affiché sur le bouton |
5.2.2.12. Champ caché
|
<input type="hidden" name="secret" value="uneValeur" /> |
|
<input type="hidden" name="..." value="..."> |
|
type="hidden" : précise que c'est un champ caché. Un champ caché fait partie du formulaire mais n'est pas présenté à l'utilisateur. Cependant, si celui-ci demandait à son navigateur l'affichage du code source, il verrait la présence de la balise <input type="hidden" value="..."> et donc la valeur du champ caché. value="uneValeur" : valeur du champ caché. Quel est l'intérêt du champ caché ? Cela peut permettre au serveur web de garder des informations au fil des requêtes d'un client. Considérons une application d'achats sur le web. Le client achète un premier article art1 en quantité q1 sur une première page d'un catalogue puis passe à une nouvelle page du catalogue. Pour se souvenir que le client a acheté q1 articles art1, le serveur peut mettre ces deux informations dans un champ caché du formulaire web de la nouvelle page. Sur cette nouvelle page, le client achète q2 articles art2. Lorsque les données de ce second formulaire vont être envoyées au serveur (submit), celui-ci va non seulement recevoir l'information (q2,art2) mais aussi (q1,art1) qui fait partie également partie du formulaire en tant que champ caché non modifiable par l'utilisateur. Le serveur web va alors mettre dans un nouveau champ caché les informations (q1,art1) et (q2,art2) et envoyer une nouvelle page de catalogue. Et ainsi de suite. |
5.3. Envoi à un serveur web par un navigateur des valeurs d'un formulaire
Nous savons déjà, grâce au chapitre précédent, comment un client transmet des informations au serveur Il le fait soit par :
- une requête HTTP GET url?param1=va1¶m2=val2&....
- une requête HTT POST url suivie d'un document contenant la chaîne de paramètres param1=va1¶m2=val2&....
Le navigateur va utiliser l'une de ces deux méthodes selon que l'attribut [method] de la balise [form] est GET ou POST. C'est ce que nous allons montrer maintenant. La page étudiée précédemment est une page statique. Afin d'avoir accès aux entêtes HTTP envoyés par le navigateur qui va demander ce document, nous la transformons en page dynamique pour un serveur web .NET (IIS ou Cassini). Le code statique précédent est placé dans un fichier [formulaire_get.aspx] et son contenu est le suivant :
<%@ 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 page de présentation ci-dessus est associée au contrôleur [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
' sauve la requête courante dans request.txt du dossier de la page
Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
Me.Request.SaveAs(requestFileName, True)
End Sub
End Class
A chaque appel du document [formulaire_get.aspx], la requête du client sera sauvegardée dans un fichier [request.txt] par la procédure Page_Init. Nous avons déjà rencontré ce mode de fonctionnement, aussi ne commenterons-nous pas plus le contrôleur.
5.3.1. Méthode GET
Faisons un premier test, où dans le code HTML du document, la balise FORM est définit de la façon suivante :
<form name="formulaire" method="get">
Nous plaçons les fichiers [formulaire_get.aspx] et [formulaire_get.aspx.vb] dans un dossier <application-path> et nous lançons le serveur Cassini avec les paramètres (<application-path>,/form2). Nous demandons l'url http://localhost/form2/formulaire_get.aspx :

Le navigateur vient de faire une requête et nous savons que celle-ci a été enregistrée dans le fichier [request.txt]. Regardons le contenu de celui-ci :
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
Le navigateur a utilisé une requête HTTP GET pour demander l'url [http://localhost/form2/formulaire_get.aspx]. C'est toujours le cas lorsque l'url est donnée par l'utilisateur. Nous remplissons le formulaire est rempli de la façon suivante :

Nous utilisons le bouton [Envoyer] ci-dessus. Son code HTML est le suivant :
Sur l'activation d'un bouton de type [Submit], le navigateur envoie les paramètres du formulaire (balise <form>) à l'URL indiquée dans l'attribut [action] de la balise <form action="URL"> s'il existe. Si cet attribut n'existe pas, les paramètres d formulaire sont envoyés à l'URL qui a délivré le formulaire. C'est le cas ici. Le bouton [Envoyer] devrait donc entraîner une requête du navigateur à l'URL [http://localhost/form2/formulaire_get.aspx] avec un transfert des paramètres du formulaire. Comme la page [formulaire_get.aspx] mémorise la requête reçue, nous devrions savoir comment le client a transféré ces paramètres. Essayons. Nous cliquons sur le bouton [Envoyer]. Nous recevons la réponse suivante du navigateur :

C'est la page initiale mais on peut remarquer que l'URL a changé dans le champ [Adresse] du navigateur. Elle est devenue la suivante :
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
On constate que les choix faits dans le formulaire se retrouvent dans l'URL. Regardons le contenu du fichier [request.txt] qui a mémorisé la requête du 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
On retrouve une requête HTTP assez semblable à celle qui avait été faite initialement par le navigateur lorsqu'il avait demandé le document sans transmettre de paramètres. Il y a deux différences :
|
Les paramètres du formulaire ont été ajoutés derrière l'URL du document sous la forme ?param1=val1¶m2=val2&... |
|
le client indique par cet entête HTTP l'URL du document qu'il affichait lorsqu'il a fait la requête |
Examinons de plus près comment les paramètres ont été passés dans la commande GET URL?param1=valeur1¶m2=valeur2&... HTTP/1.1 où les parami sont les noms des contrôles du formulaire web et valeuri les valeurs qui leur sont associées. Nous présentons ci-dessous un tableau à trois colonnes :
- colonne 1 : reprend la définition d'un contrôle HTML de l'exemple
- colonne 2 : donne l'affichage de ce contrôle dans un navigateur
- colonne 3 : donne la valeur envoyée au serveur par le navigateur pour le contrôle de la colonne 1 sous la forme qu'elle a dans la requête GET de l'exemple
|
contrôle HTML |
visuel avant validation |
valeur(s) renvoyée(s) |
|
<input type="radio" value="oui" name="rdMarie" />Oui <input type="radio" checked value="non" name="rdMarie" />Non |
|
rdMarie=oui - la valeur de l'attribut value du bouton radio coché par l'utilisateur. |
|
<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 |
|
C1=un C2=deux - valeurs des attributs value des cases cochées par l'utilisateur |
|
<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" /> |
|
txtSaisie=programmation+asp.net - texte tapé par l'utilisateur dans le champ de saisie. Les espaces ont été remplacés par le signe + |
|
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> |
|
txtMdp=ceciestsecre - texte tapé par l'utilisateur dans le champ de saisie. Le texte réellement tapé était "ceciestsecret". Le dernier caractère a été perdu parce que l'attribut maxlength="12" limitait le nombre de caractères à 12. |
|
<textarea name="areaSaisie"> ligne1 ligne2</textarea> |
|
areaSaisie=les+bases+de+ la%0D%0A programmation+web - texte tapé par l'utilisateur dans le champ de saisie. %OD%OA est la marque de fin de ligne. Les espaces ont été remplacés par le signe + |
|
<select name="cmbValeurs"> <option value="1">choix1 </option> <option value="2" selected>choix2 </option> <option value="3">choix3 </option> </select> |
|
cmbValeurs=3 - valeur choisie par l'utilisateur dans la liste à sélection unique |
|
<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> |
|
lstSimple=3 - valeur choisie par l'utilisateur dans la liste à sélection unique |
|
<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 - valeurs choisies par l'utilisateur dans la liste à sélection multiple |
|
<input type="submit" value="Envoyer" name="btnEnvoyer" /> |
|
btnEnvoyer=Envoyer - nom et attribut value du bouton qui a servi à envoyer les données du formulaire au serveur |
|
<input type="hidden" name="secret" value="uneValeur" /> |
secret=uneValeur - attribut value du champ caché |
On peut se demander ce que le serveur a fait des paramètres qu'on lui a passés. En réalité rien. A la réception de la commande
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
le serveur web a transmis les paramètres à l'URL au document [http://localhost/form2/formulaire_get.aspx], c.a.d. au document que nous avons construit initialement. Nous n'avons écrit aucun code pour récupérer et traiter les paramètres que le client nous envoie. Aussi tout se passe comme si la requête du client était simplement :
C'est pour cette raison, qu'en réponse à notre bouton [Envoyer], nous avons obtenu la même page que celle obtenue initialement en demandant l'URL [http://localhost/form2/formulaire_get.aspx] sans paramètres.
5.3.2. Méthode POST
Le document HTML est maintenant programmé pour que le navigateur utilise la méthode POST pour envoyer les valeurs du formulaire au serveur web. Pour cela, nous copions le fichier [formulaire_get.aspx] dans [formulaire_post.aspx] et modifions uniquement la balise <form> dans [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">
Il n'y a pas nécessité de changer le contrôleur [formulaire_get.aspx.vb], aussi le gardons-nous en l'état. Nous demandons le nouveau document via l'URL [http://localhost/form2/formulaire_post.aspx], nous remplissons le formulaire tel que pour la méthode GET et nous transmettons les paramètres au serveur avec le bouton [Envoyer]. Nous obtenons du serveur la page réponse suivante :

Nous obtenons donc le même résultat qu'avec la méthode GET, c.a.d. la page initiale. On remarquera une différence : dans le champ [Adresse] du navigateur, les paramètres transmis n'apparaissent pas. Maintenant, regardons la requête envoyée par le client et qui a été mémorisée dans le fichier [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
Des nouveautés apparaissent dans la requête HTTP du client :
|
la requête GET a laissé place à une requête POST. Les paramètres ne sont plus présents dans cette première ligne de la requête. On peut constater qu'ils sont maintenant placés derrière la requête HTTP après une ligne vide. Leur encodage est identique à celui qu'ils avaient dans la requête GET. |
|
nombre de caractères "postés", c.a.d. le nombre de caractères que devra lire le serveur web après avoir reçu les entêtes HTTP pour récupérer le document que lui envoie le client. Le document en question est ici la liste des valeurs du formulaire. |
|
précise le type du document que le client enverra après les entêtes HTTP. Le type [application/x-www-form-urlencoded] indique que c'est un document contenant des valeurs de formulaire. |
Il y a deux méthodes pour transmettre des données à un serveur web : GET et POST. Y-a-t-il une méthode meilleure que l'autre ? Nous avons vu que si les valeurs d'un formulaire étaient envoyées par le navigateur avec la méthode GET, le navigateur affichait dans son champ Adresse l'URL demandée sous la forme URL?param1=val1¶m2=val2&.... On peut voir cela comme un avantage ou un inconvénient :
- un avantage si on veut permettre à l'utilisateur de placer cette URL paramétrée dans ses liens favoris
- un inconvénient si on ne souhaite pas que l'utilisateur ait accès à certaines informations du formulaire tels, par exemple, les champs cachés
Par la suite, nous utiliserons quasi exclusivement la méthode POST dans nos formulaires.
5.4. Traitement côté serveur des valeurs d'un formulaire
5.4.1. Présentation de l'exemple
Maintenant que nous avons fait le lien entre la balise HTML <form method="GET/POST" ...> et la façon utilisée par le navigateur pour envoyer les valeurs du formulaire, nous savons comment côté serveur récupérer celles-ci. C'est le chapitre précédent qui nous a donné la réponse :
- si la méthode de la balise <form> est GET, les valeurs des paramètres seront récupérées dans la collection [Request.QueryString]
- si la méthode de la balise <form> est POST, les valeurs des paramètres "postés" seront récupérées dans la collection [Request.Form]. Il faut ici apporter une précision. La balise <form> peut préciser à l'aide de l'attribut [action] l'url cible du GET ou du POST. Cette url peut très bien être paramétrée qu'on ait un GET ou un POST, sous la forme action="url?param1=val1¶m2=val2&..". Ces paramètres s'ajoutent alors à ceux compris entre les balises <form> et </form> et qui vont faire l'objet d'un transfert vers le serveur au moyen d'un GET ou d'un POST. Parce qu'ils font partie de l'url cible, ils seront obtenus dans la collection [Request.QueryString] qu'on ait affaire à un GET ou à un POST.
Nous écrivons maintenant une application MVC à deux vues :
- la première vue est le formulaire précédent. Nous l'appellerons [vue_formulaire].
- la seconde vue est une page d'informations listant les valeurs saisies dans la première page. Un lien permet le retour au formulaire. Nous appellerons cette vue [vue_confirmation].
La vue [vue_formulaire] une envoyée à l'utilisateur qui la remplit et la valide. Elle pourrait ressembler à ceci juste avant la validation :

L'utilisateur utilise le bouton [Envoyer] pour valider ses saisies. Il reçoit en retour, la vue [vue_validation] suivante :

5.4.2. Le contrôleur de l'application
Nous avons vu dans le chapitre précédent, que nous pouvions confier le rôle du contrôleur d'une application MVC au fichier [global.asax] par qui transitent toutes les requêtes des clients. Nous avons déjà présenté une application MVC construite ainsi et nous suivons ici le modèle de développement présenté alors. Le fichier [global.asax] sera le suivant :
Il est constitué d'une unique ligne référençant le contrôleur placé dans le fichier [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)
' on récupère l'action à faire
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' on exécute l'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
Le principe du contrôleur est le suivant :
- il attend dans l'url cible, une chaîne de paramètres contenant le paramètre [action]. Si celui-ci est absent, on fait comme si on avait eu [action=init] dans la chaîne de paramètres.
- seules deux actions sont reconnues :
- init : on délivre au client le formulaire pré-rempli
- validation : on délivre au client la page confirmant les saisies qu'il a faites
- si l'action n'est pas l'une des précédentes, on fait comme si on avait eu [action=init]. On pourrait aussi délivrer une page d'erreur.
5.4.3. Traitement de l'action init
Lorsque le contrôleur traite l'action "init", il doit générer un formulaire pré-rempli. C'est le rôle de la page [formulaire.aspx] de faire ce travail. Son code est le suivant :
<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>
Nous retrouvons le code HTML du formulaire étudié précédemment à quelques différences près. Le code de la balise <form> a été modifié :
<form name="formulaire" method="post" action="?action=validation">
- post : les valeurs saisies par l'utilisateur puis envoyées au serveur lorsque le bouton de type [submit] sera utilisé le seront par la méthode HTTP POST
- action : la syntaxe action="url" sert à désigner l'url à laquelle doivent être envoyées les valeurs du formulaire. Cette url peut comporter une chaîne de paramètres de la forme param1=val1¶m2=val2&... C'est ce qui est fait ici où nous passons le paramètre [action=validation] pour indiquer au contrôleur l'action qu'il doit entreprendre. On peut noter que cette chaine de paramètres n'est pas précédée d'une adresse web. Le navigateur enverra alors les paramètres du formulaire à l'adresse qui lui a fournie ce formulaire. Dans notre exemple présenté plus haut, cette adresse est [http://localhost/mvcform1]. Le navigateur fera donc une requête [POST /mvcform1?action=validation] à la machine [localhost].
Des boutons ont été ajoutés afin de permettre à l'utilisateur de désélectionner les éléments des listes [lstSimple] et [lstMultiple] :

Cela se traduit par le code HTML suivant :
<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>
Un clic sur un bouton [Raz] provoque la désélection de tout élément de la liste à laquelle il est associé. Prenons l'exemple de la liste [lstMultiple]. Un clic sur le bouton [Raz] correspondant, provoque l'exécution de la fonction Javascript [raz(lstMultiple)]. Rappelons que le code Javascript d'un document HTML affiché par un navigateur est exécuté par ce même navigateur et non pas par le serveur. Javascript est un langage très complet qui permet de donner un aspect dynamique à des pages sans intervention du serveur. La fonction [raz] est la suivante :
Cette fonction reçoit un paramètre qui est un objet Javascript représentant une liste HTML. Cet objet a des propriétés et des méthodes. L'une de ses propriétés est [selectedIndex] dont la valeur est le numéro de la première option sélectionnée dans la liste HTML. S'il n'y en a pas, cette propriété vaut -1. Inversement fixer une valeur à cette propriété revient à sélectionner un nouvel élément dans la liste HTML et lui donner la valeur -1 revient à n'avoir aucun élément sélectionné. C'est ce qui est fait ici.
On remarquera enfin que le code de présentation [formulaire.aspx] n'est pas accompagné d'un contrôleur [formulaire.aspx.vb]. En effet, il n'y a aucune partie dynamique générée par le serveur dans le document HTML donc aucune nécessité d'avoir un contrôleur.
5.4.4. Traitement de l'action validation
Lorsque le contrôleur traite l'action "validation", il doit générer une page listant les valeurs saisies par l'utilisateur. C'est le rôle de la page [validation.aspx] de faire ce travail. Visuellement la page se présente de la façon suivante :

Son code HTML est le suivant :
<%@ 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>
Les parties dynamiques <%=variable%> du document sont calculées par le contrôleur [validation.aspx.vb] associé :
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
'on récupère les paramètres postés
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
' récupère la valeur du champ [champ] de la requête postée
' qq chose ?
If Request.Form(champ) Is Nothing Then Return ""
' on récupère la ou les valeurs du champ
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
Le calcul des valeurs à afficher est fait dans la procédure [Form_Load]. La valeur d'un champ "posté" est obtenue par la fonction getValue(C) où C est le nom du champ. Les points clés de cette fonction sont les suivants :
- si C n'est pas dans la chaîne de paramètres postée alors on rend la chaîne vide pour valeur de C
- sinon on obtient le tableau des valeurs du champ C par [Request.Form.GetValues(C). Celles-ci sont concaténées dans une chaîne de caractères sous la forme [val1][val2]...[valn] où [vali] est la valeur n° i du champ C
Le champ [areaSaisie] est traitée de façon particulière. Sa valeur est envoyée par le navigateur sous la forme areaSaisie=ligne1\r\nligne2\r\n... où \r est le caractère de code ASCII 13 (retour chariot) et \n le caractère de code ASCII 10 (saut de ligne). La fonction getValue(areaSaisie) est donc la chaîne "ligne1\r\nligne2\r\n...". Cette chaîne est découpée en lignes par la méthode [Regex.Split]. On obtient alors un tableau de chaînes {ligne1,ligne2,...}. Ce tableau est transformée en chaîne "ligne1,ligne2,..." par la méthode [String.Join]. C'est cette dernière chaîne qui sera affichée pour valeur du champ [areaSaisie]. Le but était ici de montrer comment on pouvait obtenir les différentes lignes d'un champ HTML de type [TextArea].
5.4.5. Tests
Nous plaçons tous les fichiers (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) dans un dossier <application-path>. Nous lançons le serveur Cassini avec les paramètres (<application-path>,/mvcform1). Nous créons dans le dossier <application-path> un fichier [default.aspx] vide puis nous demandons l'url [http://localhost/mvcform1]. Comme [/mvcform1] est le chemin virtuel d'un dossier et non d'un document, le serveur web va afficher le document [default.aspx] s'il est présent. C'est pourquoi nous avons créé celui-ci. Avant de l'afficher, le script [global.asax] va être exécuté et va finalement faire afficher la page [formulaire.aspx]. C'est pourquoi le fichier [default.aspx] peut être vide.
Supposons que le formulaire validé soit le suivant :

L'utilisation du bouton [Envoyer] renvoie la page suivante :

Remarquons tout d'abord l'url de la réponse : [http://localhost/mvcform1/?action=validation]. C'est l'URL de l'attribut [action] de la balise <form> du formulaire [formulaire.aspx] :
<form name="formulaire" method="post" action="?action=validation">
Examinons une à une les valeurs obtenues pour les différents champs du formulaire :
|
champ |
valeur |
HTML |
commentaires |
|
rdMarie |
oui |
<input type="radio" value="oui" name="rdMarie">Oui <input type="radio" checked value="non" name="rdMarie">Non |
la valeur obtenue est l'attribut [value] du bouton coché |
|
C1 |
un |
<input type="checkbox" value="un" name="C1">1 |
idem |
|
C2 |
deux |
<input type="checkbox" checked value="deux" name="C2">2 |
idem |
|
C3 |
<input type="checkbox" value="trois" name="C3">3 |
ce bouton n'a pas été coché par l'utilisateur. Sa valeur n'a alors pas été envoyée par le navigateur. Dans le code, la condition [Request.Form("C3") is Nothing] a donc été vraie. |
|
|
txtSaisie |
Programmation asp.net |
<input type="text" ... name="txtSaisie"> |
la valeur obtenue est le texte présent dans le champ de saisie au moment de la validation |
|
txtMdp |
mdp |
<input type="password" ...name="txtMdp"> |
idem |
|
areaSaisie |
les bases de la programmation web |
<textarea name="areaSaisie"> ...</textarea> |
idem |
|
cmbValeurs |
3 |
<select name="cmbValeurs"> ... <option value="3">choix3</option> </select> |
la valeur obtenue est l'attribut [value] de l'option sélectionnée |
|
lstSimple |
3 |
<select size="3" name="lstSimple"> .... <option value="3">liste3</option> ... </select> |
idem |
|
lstMultiple |
2 4 |
<select multiple size="3" name="lstMultiple"> ... <option value="2">multiple2 </option> ... <option value="4">multiple4 </option> ... </select> |
les valeurs obtenues sont celles des attributs [value] des options sélectionnées |
|
secret |
uneValeur |
<input type="hidden" name="secret" value="uneValeur"> |
la valeur obtenue est l'attribut [value] du champ caché |
Maintenant intéressons-nous aux listes. Supposons qu'au moment de la validation l'état du formulaire soit le suivant :

- l'option [choix1] est sélectionnée dans le comboBox
- aucune option n'est sélectionnée dans les deux autres listes. On a utilisé les boutons [Raz] pour obtenir cela.
Voici la page retournée après validation :

Lorsqu'aucune valeur n'est sélectionnée dans une liste, le navigateur n'envoie pas de paramètre pour celle-ci. Dans le code de [validation.aspx.vb], les expressions[Request.Form("lstSimple")] et [Request.Form("lstMultiple")] sont donc égales à la constante [Nothing] d'où le résultat affiché ci-dessus.
5.5. Maintenir l'état d'une page
5.5.1. Maintenir l'état d'une page avec une session
Nous dupliquons la totalité de l'application précédente dans un nouveau dossier. Nous ajoutons un lien dans la page [validation.aspx] permettant à l'utilisateur de revenir au formulaire :

La modification à opérer sur la page [validation.aspx] est l'ajout du lien :
.....
<TR>
<TD width="84">secret</TD>
<TD><%=secret%></TD>
</TR>
</TABLE>
<P>
<a href="?action=formulaire">Retour au formulaire</a>
</P>
</body>
</HTML>
L'attribut [href] du lien a pour valeur une url paramétrée avec pour seul paramètre [action=formulaire], permettant au serveur de savoir qu'il doit afficher le formulaire tel qu'il était lorsqu'il a été validé. Il y a donc une différence avec l'action [init] qui affiche un formulaire prédéfini. L'url paramétrée [?action=formulaire] n'a en fait pas d'url. Celle-ci sera donc la même que celle qui a permis l'affichage de la page de validation. Si on se souvient de l'étude précédente, celle-ci est l'url du dossier de l'application. La demande passera donc par le contrôleur. Celui-ci doit maintenant traiter l'action [formulaire]. Le code de [global.asax.vb] est modifié comme suit :
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' on récupère l'action à faire
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' on exécute l'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
Dans le cas où l'action est "formulaire", on se contente de passer la requête à la page [formulaire.aspx]. On sait que celle-ci affiche un formulaire prédéfini dans lequel il n'y a aucune partie variable. Cette page ne peut donc afficher le formulaire avec les valeurs qu'il avait lorsqu'il a été validé. On cherche ici à mettre en évidence ce point. Si l'ensemble des fichiers de l'application ont été placés dans <application-path>, nous lançons Cassini avec les paramètres (<application-path>,/mvcform2) puis nous demandons l'url [http://localhost/mvcform2]. Nous obtenons la page suivante (vue partielle) :

Nous remplissons le formulaire de la façon suivante puis le validons :

Nous obtenons la page de confirmation suivante :

Nous utilisons le lien [Retour au formulaire] présent (mais non représenté) sur la page ci-dessus. Nous obtenons la réponse suivante du serveur :

Nous constatons que :
- l'url demandée a bien le paramètre action=formulaire comme il était souhaité
- le formulaire affiché a perdu les valeurs saisies.
Nous savons pourquoi nous ne retrouvons pas les valeurs saisies. Si nous regardons le code du document [formulaire.aspx], nous constatons que tout est statique et qu'il est obligé ainsi d'afficher à chaque fois la même page. On voit bien qu'il nous faut rendre ce code dynamique. Il faudra qu'il affiche les valeurs validées par l'utilisateur. Mais où mémoriser celles-ci ?
Rappelons la loi d'airain du protocole sans état HTTP :
- l'url [http://localhost/mvcform2] est demandée - une réponse est reçue. Une liaison TCP-IP a été ouverte entre le client et le serveur au début de la demande et dermée à la fin de la réponse.
- l'utilisateur saisit puis valide des données. L'url [http://localhost/mvcform2/?action=validation] est demandée - une réponse est reçue. Une nouvelle connexion TCP-IP a été ouverte puis fermée entre les deux partenaires.
- l'utilisateur utilise le lien [Retour au formulaire]. L'url [http://localhost/mvcform2/?action=formulaire] est demandée - une réponse est reçue. Une nouvelle connexion TCP-IP a été de nouveau ouverte puis fermée entre les deux partenaires.
Les cycles demande-réponse sont indépendants les uns des autres parce que chacun d'eux utilise une nouvelle connexion TCP-IP. Lorsque une application client-serveur utilise une unique connexion TCP-IP pour une suite d'échanges, le serveur peut identifier un client via sa connexion. Il peut donc mémoriser des informations qu'il va lier à une connexion précise et ainsi avoir un suivi des échanges. Lorsque les échanges se font sur des connexions différentes, le serveur ne peut identifier un client à une connexion. Il faut un autre moyen. Nous avons présenté l'un d'eux dans le chapitre précédent : le mécanisme de la session. Il permet aux cycles demande-réponse de mémoriser des informations dans un objet [Session] accessible à tous les cycles successifs.
Maintenant que nous avons une application MVC avec session, nous ne pouvons plus utiliser le fichier [global.asax] comme contrôleur comme il a été montré au chapitre précédent. Le rôle de contrôleur d'application doit être joué par une page particulière dédiée à cela. Ici, ce sera la page [main.aspx]. Nous procéderons ainsi :
- lorsque l'utilisateur validera ses données (action=validation), le contrôleur [main.aspx.vb] les mémorisera dans la session courante avant de faire afficher la page de validation.
- lorsqu'il faudra faire afficher le formulaire avec les valeurs saisies (action=formulaire), le contrôleur [main.aspx.vb] les récupèrera dans la session et les mettra dans le contexte avant de faire afficher le formulaire.
5.5.2. Le nouveau contrôleur d'application
Le contrôleur d'application est formé des deux fichiers [main.aspx, main.aspx.vb] :
[main.aspx]
[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
' on récupère l'action à faire
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' on exécute l'action
Select Case action
Case "init"
' on affiche le formulaire pré-rempli
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
Case "validation"
' on affiche la page de confirmation après avoir enregistré les valeurs postées dans la session
Session.Item("formulaire") = Request.Form
Server.Transfer("validation.aspx", True)
Case "formulaire"
' on affiche le formulaire avec des valeurs prises dans la session
Context.Items("formulaire") = Session.Item("formulaire")
Server.Transfer("formulaire.aspx", True)
Case Else
' on affiche le formulaire pré-rempli
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
Private Function initForm() As NameValueCollection
' on initialise le formulaire
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
On retrouve l'essence de la structure du contrôleur d'application étudié précédemment avec les différences suivantes :
- le travail du contrôleur se fait dans la procédure [Form_Load]
- dans le cas de l'action [validation], les valeurs du formulaire présentes dans [Request.Form] sont stockées dans la session associées à la clé "formulaire". Ensuite l'exécution est transférée à la page [validation.aspx] qui affichera ces valeurs.
- pour les autres actions, l'exécution est transférée dans tous les cas à la page [formulaire.aspx]. Celle-ci attend dans son contexte une clé "formulaire" qui sera associée à un objet du type de [Request.form] c.a.d. de type [NameValueCollection]. Cet objet doit contenir la collection des valeurs des champs du formulaire.
- dans le cas où l'action est [init] ou une action non reconnue, la collection des valeurs est construite arbitrairement par la fonction [initForm].
- dans le cas où l'action est [formulaire], cette collection est la collection [Request.Form] qui avait été placée dans la session par l'action [validation]
5.5.3. Le nouveau formulaire
Parce que l'application n'affiche plus le même contenu dans le formulaire, celui-ci doit être généré dynamiquement. La nouvelle page [formulaire.aspx] devient la suivante :
<%@ 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>
Commentons les variables dynamiques qui apparaissent dans le code HTML :
|
variable |
rôle |
|
aura la valeur "checked" si le bouton radio [oui] doit être coché, la valeur "" sinon |
|
idem pour le bouton radio [non] |
|
idem pour la case à cocher [C1] |
|
idem pour la case à cocher [C2] |
|
idem pour la case à cocher [C3] |
|
le texte à placer dans le champ [txtSaisie] |
|
le texte à placer dans le champ [txtMdp] |
|
le texte à placer dans le champ [areaSaisie] |
|
le texte HTML des options de la liste select [cmbValeurs] |
|
le texte HTML des options de la liste select [lstSimple] |
|
le texte HTML des options de la liste select [lstMultiple] |
Les valeurs de ces variables sont calculées par le contrôleur de la page [formulaire.aspx.vb] :
Imports Microsoft.VisualBasic
Imports System.Collections.Specialized
Public Class formulaire
Inherits System.Web.UI.Page
' champs constants du formulaire
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"}
' champs dynamiques du formulaire
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
' on récupère la précédente requête dans la session
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
' on prépare la page à afficher
' boutons radio
rdouichecked = ""
rdnonchecked = "checked"
If isEqual(form("rdMarie"), "oui") Then
rdouichecked = "checked"
rdnonchecked = ""
End If
' cases à cocher
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"
' champs de saisie
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
' listes
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
' rend le code HTML des options d'une balise <select>
' valeurs : tableau des valeurs des options de la balise
' libelles : tableau des libellés des options de la balise
' sélections : options à sélectionner
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' on parcourt la liste des valeurs des options
For iValeur = 0 To valeurs.Length - 1
' on regarde si la valeur courante doit être sélectionnée
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' on intègre le code HTML de l'option
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' on rend le résultat
Return toString
End Function
Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
' rend vrai si le champ est égal à valeur
If champ Is Nothing OrElse champ.ToString <> valeur Then
Return false
Else
Return true
End If
end function
End Class
Lorsque la page [formulaire.aspx] commence à s'exécuter, elle va trouver dans son contexte une clé "formulaire" associée à la collection de valeurs des champs qu'elle doit afficher.
' on récupère la précédente requête dans la session
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
On peut se demander pourquoi vérifie-t-on que [Context.Items("formulaire")] existe. En effet, le contrôleur affecte une valeur à cet objet dans tous les cas. Cependant, rien n'empêche le client de demander directement la page [formulaire.aspx] sans passer par le contrôleur. Si c'était le cas, le code précédent travaillera avec une collection de valeurs vide mais il n'y aura pas de "plantage".
Le code explore la collection de valeurs qu'il a reçues pour calculer toutes les variables dynamiques de la page HTML qui lui est associée. Même s'il est long, ce code n'est pas spécialement compliqué et nous laissons le lecteur s'y plonger afin de ne pas alourdir cette explication. Nous nous attarderons cependant à la façon de générer le code HTML des trois listes de type [select]. Ce code est généré par la fonction suivante :
Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
' rend le code HTML des options d'une balise <select>
' valeurs : tableau des valeurs des options de la balise
' libelles : tableau des libellés des options de la balise
' sélections : options à sélectionner
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' on parcourt la liste des valeurs des options
For iValeur = 0 To valeurs.Length - 1
' on regarde si la valeur courante doit être sélectionnée
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' on intègre le code HTML de l'option
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' on rend le résultat
Return toString
End Function
Rappelons que les options d'une balise <select> correspondent au code HTML suivant :
Pour chaque option, il y a donc trois informations à générer :
- la valeur de l'option dans l'attribut [value]
- le texte de l'option entre les balises <option> et </option>
- le mot clé [selected] si l'option doit être sélectionnée dans la liste
Pour générer ces trois informations pour chacune des options, la fonction [getOptions] reçoit trois valeurs :
- le tableau des valeurs des options dans [valeurs]
- le tableau des textes des options dans [libelles]
- le tableau des valeurs à sélectionner dans [sélections]
5.5.4. La page de validation
La page de validation reste inchangée :
[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
'on récupère les paramètres postés
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")
' on les sauvegarde dans la session
'Session("formulaire") = Request.Form
End Sub
Private Function getValue(ByVal champ As String) As String
' récupère la valeur du champ [champ] de la requête postée
' qq chose ?
If Request.Form(champ) Is Nothing Then Return ""
' on récupère la ou les valeurs du champ
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. Les tests
Les fichiers [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] sont placés dans <application-path> et Casini lancé avec les paramètres (<application-path>,/mvcform3). Nous demandons ensuite l'url [http://localhost/mvcform3/main.aspx]. Nous obtenons le formulaire pré-initialisé :

Nous remplissons le formulaire de la façon suivante :

Nous utilisons le bouton [Envoyer] ci-dessus. Nous obtenons la réponse suivante du serveur :

Nous utilisons le lien [Retour au formulaire] ci-dessus pour revenir au formulaire. Nous obtenons la nouvelle réponse suivante :

Nous retrouvons bien le formulaire tel que nous l'avons validé.
5.5.6. Conclusion
L'exemple précédent nous a montré qu'il était possible de maintenir l'état d'une page au fil des cycles demande-réponse entre le client et le serveur. Néanmoins, ce travail n'est pas trivial. Nous verrons dans un chapitre ultérieur qu'il est possible avec ASP.NET de laisser le serveur rétablir de lui-même l'état d'une page.