Skip to content

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&param2=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&param2=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

Image

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

Image

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] :

Image

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

Image

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é :

Image

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 :

Image

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

Image

  • nous ajoutons le composant [Table] :

Image

  • 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 :

Image

  • 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 :

Image

  • 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> :

Image

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

Image

  • 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] :

Image

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

Image

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

Image

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

Image

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

Image

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

Image

  • 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] :

Image

  • nous obtenons le résultat suivant :

Image

  • 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 :

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

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

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

devient :

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

La fenêtre [Design] reflète nos changements :

Image

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] :

Image

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

Image

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

Image

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 :

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

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


titre du document

<title>HTML1</title>

HTML1 apparaîtra dans la barre de titre du navigateur qui affichera le document


barre horizontale

<hr> : affiche un trait horizontal


tableau

<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")


image

<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.


lien

<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 :

Image

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


formulaire

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


champ de saisie

<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" />


champ de saisie cachée

<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />


champ de saisie multilignes

<textarea name="areaSaisie">ligne1

ligne2</textarea>


boutons radio

<input type="radio" value="oui" name="rdMarie" />Oui

<input type="radio" checked value="non" name="rdMarie" />Non


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


Combo

<select name="cmbValeurs">

<option value="1">choix1</option>

<option value="2" selected>choix2</option>

<option value="3">choix3</option>

</select>


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>


liste à sélection multiple

<select multiple size="3" name="lstMultiple">

<option value="1" selected>multiple1</option>

<option value="2">multiple2</option>

<option value="3" selected>multiple3</option>

<option value="4">multiple4</option>

<option value="5">multiple5</option>

</select>


champ caché

<input type="hidden" name="secret" value="uneValeur" />


bouton de type submit

<input type="submit" value="Envoyer" name="btnEnvoyer" />


bouton de type reset

<input type="reset" value="Rétablir" name="btnRetablir" runat="server" />


bouton de type button

<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" />

Passons en revue ces différents contrôles.

5.2.2.1. Le formulaire


formulaire

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


balise HTML

<form name="..." method="..." action="...">...</form>


attributs

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

Image


champ de saisie

<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" />

<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />


balise HTML

<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.


attributs

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

Image


champ de saisie multilignes

<textarea name="areaSaisie">ligne1

ligne2</textarea>


balise HTML

<textarea ...>texte</textarea>

affiche une zone de saisie multilignes avec au départ texte dedans


attributs

rows="2" : nombre de lignes

cols="'20" : nombre de colonnes

name="areaSaisie" : nom du contrôle

5.2.2.4. Boutons radio

Image


boutons radio

<input type="radio" value="oui" name="rdMarie" />Oui

<input type="radio" checked value="non" name="rdMarie" />Non


balise HTML

<input type="radio" attribut2="valeur2" ..../>texte

affiche un bouton radio avec texte à côté.


attributs

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


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

Image


balise HTML

<input type="checkbox" attribut2="valeur2" ..../>texte

affiche une case à cocher avec texte à côté.


attributs

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)


Combo

<select name="cmbValeurs">

<option value="1">choix1</option>

<option value="2" selected>choix2</option>

<option value="3">choix3</option>

</select>

Image


balise HTML

<select size=".." name="..">

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

...

</select>

affiche dans une liste les textes compris entre les balises <option>...</option>


attributs

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


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>

Image


balise HTML

<select size=".." name="..">

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

...

</select>

affiche dans une liste les textes compris entre les balises <option>...</option>


attributs

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


liste à sélection multiple

<select multiple size="3" name="lstMultiple">

<option value="1" selected>multiple1</option>

<option value="2">multiple2</option>

<option value="3" selected>multiple3</option>

<option value="4">multiple4</option>

<option value="5">multiple5</option>

</select>

Image


balise HTML

<select size=".." name=".." multiple>

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

...

</select>

affiche dans une liste les textes compris entre les balises <option>...</option>


attributs

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


bouton de type button

<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" />

Image


balise HTML

<input type="button" value="..." name="..." onclick="effacer()" ....>


attributs

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 :


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

La fonction effacer affiche un message :

Image

5.2.2.10. Bouton de type submit


bouton de type submit

<input type="submit" value="Envoyer" name="btnEnvoyer" />

Image


balise HTML

<input type="submit" value="Envoyer" name="btnEnvoyer">


attributs

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


bouton de type reset

<input type="reset" value="Rétablir" name="btnRetablir" runat="server" />

Image


balise HTML

<input type="reset" value="Rétablir" name=" btnRetablir ">


attributs

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é


champ caché

<input type="hidden" name="secret" value="uneValeur" />


balise HTML

<input type="hidden" name="..." value="...">


attributs

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&param2=val2&....
  • une requête HTT POST url suivie d'un document contenant la chaîne de paramètres param1=va1&param2=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 :

Image

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 :

Image

Nous utilisons le bouton [Envoyer] ci-dessus. Son code HTML est le suivant :

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

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 :

Image

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 :


GET URL HTTP/1.1

Les paramètres du formulaire ont été ajoutés derrière l'URL du document sous la forme ?param1=val1&param2=val2&...


Referer

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&param2=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

Image

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

Image

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" />

Image

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" />

Image

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>

Image

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>

Image

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>

Image

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>

Image

lstMultiple=2

lstMultiple=4

- valeurs choisies par l'utilisateur dans la

liste à sélection multiple

<input type="submit"

value="Envoyer"

name="btnEnvoyer" />

Image

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 :

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

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 :

Image

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 :


POST URL HTTP/1.1

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.


Content-Length

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.


Content-type

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&param2=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&param2=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 :

Image

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

Image

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 :

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

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&param2=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] :

Image

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 :

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

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 :

Image

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 :

Image

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

Image

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 :

Image

  • 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 :

Image

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 :

Image

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) :

Image

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

Image

Nous obtenons la page de confirmation suivante :

Image

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 :

Image

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]

<%@ 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
       ' 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


rdouichecked

aura la valeur "checked" si le bouton radio [oui] doit être coché, la valeur "" sinon


rdnonchecked

idem pour le bouton radio [non]


c1checked

idem pour la case à cocher [C1]


c2checked

idem pour la case à cocher [C2]


c3checked

idem pour la case à cocher [C3]


txtSaisie

le texte à placer dans le champ [txtSaisie]


txtMdp

le texte à placer dans le champ [txtMdp]


areaSaisie

le texte à placer dans le champ [areaSaisie]


cmbValeursOptions

le texte HTML des options de la liste select [cmbValeurs]


lstSimpleOptions

le texte HTML des options de la liste select [lstSimple]


lstMultipleOptions

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 :

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

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 :

  1. le tableau des valeurs des options dans [valeurs]
  2. le tableau des textes des options dans [libelles]
  3. 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é :

Image

Nous remplissons le formulaire de la façon suivante :

Image

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

Image

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

Image

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.