Skip to content

5. Gestão da interface do utilizador

5.1. Introduction

Na relação cliente-servidor da Web, o cliente transmite informações ao servidor sob a forma de uma cadeia de parâmetros [param1=val1&param2=val2&...]. Nos nossos exemplos anteriores, construímos essa cadeia, na maioria das vezes, manualmente, solicitando URLs do tipo [http://localhost/appli? param1=val1&param2=val2&...]. Na realidade, as informações que o cliente transmite ao servidor provêm de formulários preenchidos pelo utilizador. Neste capítulo, exploramos a construção desses formulários. Apresentamos também a ferramenta WebMatrix, que nos permitirá desenhar as interfaces de utilizador. A instalação desta ferramenta é apresentada nos anexos.

5.2. A linguagem HTML

5.2.1. Um exemplo

Consideremos o exemplo seguinte, criado com o [Web Matrix], que apresenta:

  • um quadro
  • uma imagem
  • um link

Image

Executemos o [WebMatrix] e, em seguida, selecionemos a opção [File/New File]:

Image

Optamos por criar uma página HTML. As informações acima irão criar um ficheiro [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm]. O [WebMatrix] oferece duas possibilidades para editar este ficheiro: o modo [Design] e o modo [HTML]:

Image

O modo [Design] permite utilizar a paleta de componentes HTML disponibilizada pelo [WebMatrix]:

Image

Para inserir um elemento desta paleta, basta clicar duas vezes nele e, em seguida, posicioná-lo na janela [Design]. O modo [HTML] permite criar o documento HTML com a ajuda de um editor de texto. Para tal, é necessário conhecer a sintaxe da linguagem HTML. No separador [HTML], foi gerado um esboço de documento:

Image

A janela [HTML] é muito útil para quem não conhece a linguagem HTML. O utilizador cria o seu documento na janela [Design] e verifica o código HTML gerado na janela [HTML]. Desta forma, vai adquirindo progressivamente o domínio do HTML e consegue, com bastante rapidez, trabalhar apenas com o editor de texto, sem a ajuda do modo [Design]. Vamos agora mostrar como construir o documento HTML apresentado no início desta secção. Estamos a trabalhar na janela [Design]. Em primeiro lugar, introduzimos diretamente a primeira linha de texto:

Image

  • adicionamos o componente [Horizontal Rule] na paleta de componentes:

Image

  • adicionamos o componente [Table]:

Image

  • colocamos o cursor na terceira linha da tabela para a eliminar com a opção [HTML/Edit Table/Delete Table Row]. Em seguida, introduzimos o texto pretendido em cada célula:

Image

  • colocamos o cursor numa das células da tabela e consultamos as suas propriedades. A janela de propriedades é apresentada no canto inferior direito do ambiente de trabalho:

Image

  • a célula é representada pela baliza HTML <TD>. São-nos, portanto, apresentadas as propriedades da baliza <TD>. Centramo-nos na tabela, que é um objeto que engloba a célula. Clicamos na lista suspensa (clique para ver os elementos pai HTML) acima para selecionar o objeto <TABLE>:

Image

  • O objeto <TABLE> possui uma propriedade [border] que define a largura da borda que circunda as células da tabela. Aqui, definimos border=1.

Image

  • editamos agora os atributos do objeto <TD> da célula (1,2) para definir align=Center e width=200 (pixels). O texto ficará centrado na célula (align=center) e esta terá 200 píxeis de largura. Para ver a alteração, poderá, por vezes, ser necessário selecionar o separador [HTML] e, em seguida, voltar ao separador [Design]:

Image

  • agora colocamos o texto que precede a imagem:

Image

  • e, em seguida, a imagem, clicando duas vezes no componente [image] da paleta:

Image

  • Selecionamos a imagem para editar as suas propriedades:

Image

  • no atributo [src], introduzimos o nome do ficheiro que contém a imagem, neste caso [univ01.gif]:

Image

  • colocamos o texto que precede o link:

Image

  • transformamos o texto [ici] num link para o URL [http://istia.univ-angers.fr]. Para isso, selecionamo-lo e escolhemos a opção [HTML/Insert Hyperlink]:

Image

  • obtemos o seguinte resultado:

Image

  • Estamos quase lá. Vejamos o código HTML gerado no separador [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>

Ainda temos alguns detalhes a resolver. Em primeiro lugar, gostaríamos de atribuir um título ao nosso documento. O [WebMatrix] não permite fazê-lo no modo [Design]. No separador [HTML], substituímos a sequência <head>..</head> pela seguinte sequência:

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

Além disso, gostaríamos de ter o texto [Le langage HTML - 1] em caracteres maiores. A sequência <Hi>texto</Hi> permite definir o tamanho de um texto, sendo que i varia de 1 a 6, do maior para o menor. Neste caso, utilizaremos H2. A sequência

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

torna-se:

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

A janela [Design] reflete as nossas alterações:

Image

Resta-nos apenas testar utilizando a opção [View/Start] ou [F5]. A opção [WebMatrix] requer algumas informações para iniciar o servidor Web [Cassini]:

Image

Podemos aceitar os valores propostos por predefinição. O servidor [Cassini] é iniciado e a nossa página é apresentada num navegador:

Image

Por curiosidade, podemos verificar com que parâmetros foi iniciado o [Cassini]:

Image

Apresentámos os princípios básicos da construção de uma página HTML com o [WebMatrix]. Convidamos o leitor a criar outras páginas HTML e a verificar, em cada ocasião, o código HTML gerado. Aos poucos, será capaz de criar uma página sem a ajuda do modo [Design]. Um documento HTML tem a seguinte estrutura geral:

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

Todo o documento é delimitado pelas balizas <html>...</html>. É composto por duas partes:

<head>...</head>: esta é a parte não visível do documento. Fornece informações ao navegador que irá apresentar o documento. Nesta parte encontra-se frequentemente a baliza <title>...</title>, que define o texto a apresentar na barra de título do navegador. Também podem existir outras balizas, nomeadamente as que definem as palavras-chave do documento, palavras-chave posteriormente utilizadas pelos motores de busca. Nesta parte também podem encontrar-se scripts, na maioria das vezes escritos em JavaScript ou VBScript, que serão executados pelo navegador.

<body atributos>...</body>: esta é a parte que será apresentada pelo navegador. As balizas HTML contidas nesta parte indicam ao navegador a forma visual «desejada» para o documento. Cada navegador interpretará estas balizas à sua maneira. Dois navegadores podem, assim, visualizar de forma diferente um mesmo documento web. Este é, geralmente, um dos desafios dos web designers.

O código HTML do documento anterior era o seguinte:

<html>
<head>
    <title>HTML1</title>
</head>
<body>
    <h2>Le langage HTML - 1 
    </h2>
    <hr />
    <table border="1">
        <tbody>
            <tr>
                <td>
                    cellule(1,1)</td>
                <td align="middle" width="200">
                    cellule(1,2)</td>
                <td>
                    cellule(1,3)</td>
            </tr>
            <tr>
                <td>
                    cellule(2,1)</td>
                <td>
                    cellule(2,2)</td>
                <td>
                    cellule(2,3)</td>
            </tr>
        </tbody>
    </table>
    <p>
        Une image <img src="univ01.gif" /> 
    </p>
    <p>
        Le site de l'istia <a href="http://istia.univ-angers.fr">ici</a> 
    </p>
</body>
</html>
Elemento
etiquetas e exemplos HTML
titre du document
<title>HTML1</title>
HTML1 aparecerá na barra de título do navegador que exibirá o documento
barre horizontale
<hr>: exibe uma linha horizontal
tableau
<atributos da tabela>....</table>: para definir a tabela
<tr atributos>...</tr>: para definir uma linha
<td atributos>...</td>: para definir uma célula
exemplos:
<table border="1">...</table>: o atributo border define a espessura da borda da tabela
<td align="center" width="200">célula(1,2)</td>: define uma célula cujo conteúdo será cellule(1,2). Este conteúdo será centrado horizontalmente (align="center"). A célula terá uma largura de 200 píxeis (width="200")
image
<img src="univ01.gif" />: define uma imagem cujo ficheiro de origem é o univ01.gif no servidor web (src="univ01.gif"). Esta ligação encontra-se num documento web obtido com o URL http://localhost/exemple1.htm. Assim, o navegador irá solicitar o URL http://localhost/univ01.gif para obter a imagem aqui referenciada.
lien
<a href="http://istia.univ-angers.fr">aqui</a>: faz com que o texto ici funcione como um link para o URL http://istia.univ-angers.fr.

Neste exemplo simples, verifica-se que, para construir o documento na íntegra, o navegador tem de efetuar duas solicitações ao servidor:

http://localhost/exemple1.htm para obter o código-fonte HTML do documento

http://localhost/univ01.gif para obter a imagem univ01.gif

5.2.2. Criação de um formulário

Um formulário HTML tem como objetivo apresentar ao utilizador uma página de introdução de informações semelhante aos formulários de introdução de dados encontrados no Windows. O formulário de introdução de dados é enviado ao navegador na forma de um documento HTML. Este irá apresentar o formulário ao utilizador, que o preencherá e validará através de um botão com essa função. O navegador transmitirá então os valores introduzidos ao servidor para processamento. Ver-se-á que não reenvia ao servidor a totalidade do formulário, mas apenas os valores introduzidos. O exemplo seguinte apresenta um formulário Web também criado com WebMatrix:

Image

O código HTML gerado pelo [WebMatrix] é o seguinte:


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

A correspondência entre a verificação visual e a etiqueta HTML é a seguinte:

Controlo
etiqueta HTML
formulaire
<form name="formulário" method="post">
champ de saisie
<input type="text" maxlength="30" value="algumas palavras" 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">linha1
linha2</textarea>
boutons radio
<input type="radio" value="sim" name="rdMarie" />Sim
<input type="radio" checked value="não" name="rdMarie" />Não
cases à cocher
<input type="checkbox" value="um" name="C1" />1
<input type="checkbox" checked value="dois" name="C2" />2
<input type="checkbox" value="três" name="C3" />3
Combo
<select name="cmbValeurs">
<option value="1">opção1</option>
<option value="2" selected>opção 2</option>
<option value="3">opção 3</option>
</select>
liste à sélection unique
<select size="3" name="lstSimple">
<option value="1" selected>lista1</option>
<option value="2">lista2</option>
<option value="3">lista3</option>
<option value="4">lista4</option>
<option value="5">lista5</option>
</select>
liste à sélection multiple
<select multiple size="3" name="lstMultiple">
<option value="1" selected>múltiplo1</option>
<option value="2">múltiplo2</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="Enviar" name="btnEnvoyer" />
bouton de type reset
<input type="reset" value="Redefinir" name="btnRetablir" runat="server" />
bouton de type button
<input onclick="effacer()" type="button" value="Apagar" name="btnEffacer" />

Vamos analisar estes diferentes controlos.

5.2.2.1. O formulário

formulaire
<form name="formulário" method="post">
balise HTML
<form name="..." method="..." action="...">...</form>
attributs
name="frmexemple": nome do formulário
method="..." : método utilizado pelo navegador para enviar ao servidor web os valores recolhidos no formulário
action="..." : URL para onde serão enviados os valores recolhidos no formulário.
Um formulário web é delimitado pelas balizas <form>...</form>. O formulário pode ter um nome (name="xx"). É o caso de todos os controlos que se podem encontrar num formulário. Este nome é útil se o documento web contiver scripts que precisem de referenciar elementos do formulário. O objetivo de um formulário é recolher as informações fornecidas pelo utilizador através do teclado/rato e enviá-las para uma URL do servidor web. Qual? Aquela referenciada no atributo action="URL". Se este atributo estiver ausente, as informações serão enviadas para o servidor do documento em que o formulário se encontra. Como é que um cliente web transmite informações (as contidas no formulário) a um servidor web? Já vimos isso em pormenor. Pode utilizar dois métodos diferentes, denominados POST e GET. O atributo method="méthode", com o método igual a GET ou POST, da baliza <form> indica ao navegador o método a utilizar para enviar as informações recolhidas no formulário para o URL especificado pelo atributo action="URL". Quando o atributo method não é especificado, o método GET é utilizado por predefinição.

5.2.2.2. Campo de introdução

Image

champ de saisie
<input type="text" maxlength="30" value="algumas palavras" name="txtSaisie" />
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
balise HTML
<input type="..." name="..." size=".." value="..">
A tag input existe para vários controlos. É o atributo type que permite diferenciar estes controlos uns dos outros.
attributs
type="text": especifica que se trata de um campo de introdução de dados
type="password": os caracteres presentes no campo de introdução são substituídos por asteriscos (*). Esta é a única diferença em relação ao campo de introdução normal. Este tipo de controlo é adequado para a introdução de palavras-passe.
size="12": número de caracteres visíveis no campo — não impede a introdução de mais caracteres
maxlength="30": define o número máximo de caracteres em 30 — cabe ao navegador garantir o cumprimento deste atributo
name="txtSaisie": nome do controlo
value="algumas palavras": texto que será exibido no campo de introdução.

5.2.2.3. Campo de introdução de texto com várias linhas

Image

champ de saisie multilignes
<textarea name="areaSaisie">linha1
linha 2</textarea>
balise HTML
<textarea ...>texto</textarea>
exibe uma área de introdução de texto com várias linhas, com texto preenchido inicialmente
attributs
rows="2": número de linhas
cols="'20": número de colunas
name="areaSaisie": nome do controlo

5.2.2.4. Botões de opção

Image

boutons radio
<input type="radio" value="sim" name="rdMarie" />Sim
<input type="radio" checked value="não" name="rdMarie" />Não
balise HTML
<input type="radio" atributo2="valor2" ..../>texto
exibe um botão de opção com texto ao lado.
attributs
name="rdMarie": nome do controlo. Os botões de opção com o mesmo nome formam um grupo de botões mutuamente exclusivos: só é possível selecionar um deles.
value="valor": valor atribuído ao botão de opção. Não se deve confundir este valor com o texto apresentado ao lado do botão de opção. Este último destina-se apenas à visualização.
checked: se esta palavra-chave estiver presente, o botão de opção está marcado; caso contrário, não está.

5.2.2.5. Caixas de seleção

cases à cocher
<input type="checkbox" value="um" name="C1" />1
<input type="checkbox" checked value="dois" name="C2" />2
<input type="checkbox" value="três" name="C3" />3

Image

balise HTML
<input type="checkbox" atributo2="valor2" ..../>texto
exibe uma caixa de seleção com texto ao lado.
attributs
name="C1": nome do controlo. As caixas de seleção podem ou não ter o mesmo nome. As caixas com o mesmo nome formam um grupo de caixas associadas.
value="valor": valor atribuído à caixa de seleção. Não se deve confundir este valor com o texto exibido ao lado do botão de opção. Este último destina-se apenas à exibição.
checked: se esta palavra-chave estiver presente, o botão de opção está marcado; caso contrário, não está.

5.2.2.6. Lista suspensa (combo)

Combo
<select name="cmbValeurs">
<option value="1">opção1</option>
<option value="2" selected>opção 2</option>
<option value="3">opção 3</option>
</select>

Image

balise HTML
<select size=".." name="..">
<option [selected="selected"] [value="valeur"]>texto</option>
...
</select>
exibe numa lista os textos contidos entre as balizas <option>...</option>
attributs
name="cmbValeurs": nome do controlo.
size="1": número de elementos da lista visíveis. size="1" transforma a lista no equivalente a uma caixa de seleção. Este é o valor por predefinição se o atributo [size] estiver ausente.
selected="selected": se esta palavra-chave estiver presente num elemento da lista, este aparece selecionado na lista. No nosso exemplo acima, o elemento da lista choix2 aparece como o elemento selecionado na lista suspensa quando esta é apresentada pela primeira vez.
value="valor": define o valor a enviar para o servidor se o elemento for selecionado. Se este atributo estiver ausente, é então o texto associado à opção que é enviado para o servidor.

5.2.2.7. Lista de seleção única

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

Image

balise HTML
<select size=".." name="..">
<option [selected] [value="valeur"]>...</option>
...
</select>
exibe numa lista os textos entre as balizas <option>...</option>
attributs
os mesmos que para a lista suspensa que apresenta apenas um elemento. Este controlo difere da lista suspensa anterior apenas pelo seu atributo size>1.

5.2.2.8. Lista de seleção múltipla

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>
exibe numa lista os textos entre as balizas <option>...</option>
attributs
múltiplo: permite a seleção de vários elementos na lista. No exemplo acima, os elementos liste1 e liste3 estão ambos selecionados.

5.2.2.9. Botão do tipo «button»

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

Image

balise HTML
<input type="button" value="..." name="..." onclick="effacer()" ....>
attributs
type="button": define um controlo de botão. Existem outros dois tipos de botão: os tipos submit e reset.
value="Apagar": o texto exibido no botão
onclick="função()": permite definir uma função a executar quando o utilizador clica no botão. Esta função faz parte dos scripts definidos no documento web apresentado. A sintaxe anterior é uma sintaxe javascript. Se os scripts forem escritos em VBScript, deve escrever-se onclick="função" sem os parênteses. A sintaxe torna-se idêntica se for necessário passar parâmetros para a função: onclick="função(val1, val2,...)"
No nosso exemplo, um clique no botão Effacer chama a seguinte função JavaScript effacer:

        <script language="javascript">
        function effacer(){
            alert("Vous avez cliqué sur le bouton [Effacer]");
        }
        </script>
A função effacer apresenta uma mensagem:

5.2.2.10. Botão do tipo «submit»

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

Image

balise HTML
<input type="submit" value="Enviar" name="btnEnvoyer">
attributs
type="submit": define o botão como um botão para enviar os dados do formulário para o servidor web. Quando o utilizador clicar neste botão, o navegador enviará os dados do formulário para o URL definido no atributo action da tag <form>, de acordo com o método definido pelo atributo method dessa mesma tag.
value="Enviar": o texto exibido no botão

5.2.2.11. Botão do tipo «reset»

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

Image

balise HTML
<input type="reset" value="Restaurar" name=" btnRetablir ">
attributs
type="reset": define o botão como um botão de reinicialização do formulário. Quando o utilizador clicar neste botão, o navegador irá repor o formulário no estado em que o recebeu.
value="Restaurar": o texto exibido no botão

5.2.2.12. Campo oculto

champ caché
<input type="hidden" name="secret" value="uneValeur" />
balise HTML
<input type="hidden" name="..." value="...">
attributs
type="hidden": indica que se trata de um campo oculto. Um campo oculto faz parte do formulário, mas não é apresentado ao utilizador. No entanto, se este solicitasse ao seu navegador a visualização do código-fonte, veria a presença da baliza <input type="hidden" value="..."> e, consequentemente, o valor do campo oculto.
value="umValor": valor do campo oculto.
Qual é a utilidade do campo oculto? Este permite que o servidor web guarde informações ao longo das solicitações de um cliente. Consideremos uma aplicação de compras na web. O cliente compra um primeiro artigo art1 na quantidade q1 numa primeira página de um catálogo e, em seguida, passa para uma nova página do catálogo. Para se lembrar de que o cliente comprou q1 artigos art1, o servidor pode colocar estas duas informações num campo oculto do formulário web da nova página. Nesta nova página, o cliente compra os artigos q2 e art2. Quando os dados deste segundo formulário forem enviados para o servidor (submit), este irá receber não só a informação (q2,art2), mas também (q1,art1), que também faz parte do formulário como um campo oculto não modificável pelo utilizador. O servidor web irá então colocar num novo campo oculto as informações (q1,art1) e (q2,art2) e enviar uma nova página do catálogo. E assim sucessivamente.

5.3. Envio de valores de um formulário para um servidor web através de um navegador

Já sabemos, graças ao capítulo anterior, como é que um cliente transmite informações ao servidor. Faz-o através de:

  • uma solicitação com a URL HTTP GET?param1=va1&param2=val2&....
  • uma solicitação HTT POST url seguida de um documento que contém a cadeia de parâmetros param1=va1&param2=val2&....

O navegador utilizará um destes dois métodos, dependendo de o atributo [method] da baliza [form] ser GET ou POST. É isso que vamos mostrar agora. A página analisada anteriormente é uma página estática. Para ter acesso aos cabeçalhos HTTP enviados pelo navegador que irá solicitar este documento, transformamo-la numa página dinâmica para um servidor web .NET (IIS ou Cassini). O código estático anterior é colocado num ficheiro [formulaire_get.aspx] e o seu conteúdo é o seguinte:


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

A página de apresentação acima está associada ao controlador [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
        ' guarda a solicitação atual em request.txt na pasta da página
        Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
        Me.Request.SaveAs(requestFileName, True)
    End Sub
End Class

Sempre que o documento [formulaire_get.aspx] for chamado, o pedido do cliente será guardado num ficheiro [request.txt] pela rotina Page_Init. Já nos deparámos com este modo de funcionamento, pelo que não faremos mais comentários sobre o controlador.

5.3.1. Método GET

Vamos fazer um primeiro teste, em que, no código HTML do documento, a baliza FORM é definida da seguinte forma:


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

Colocamos os ficheiros [formulaire_get.aspx] e [formulaire_get.aspx.vb] numa pasta <application-path> e iniciamos o servidor Cassini com os parâmetros (<application-path>,/form2). Acedemos à URL http://localhost/form2/formulaire_get.aspx:

Image

O navegador acabou de efetuar uma solicitação e sabemos que esta foi registada no ficheiro [request.txt]. Vejamos o conteúdo deste ficheiro:

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

O navegador utilizou uma solicitação HTTP GET para solicitar a URL [http://localhost/form2/formulaire_get.aspx]. Isto acontece sempre que a URL é fornecida pelo utilizador. Preenchemos o formulário da seguinte forma:

Image

Utilizamos o botão [Envoyer] acima. O seu código HTML é o seguinte:

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

Ao clicar num botão do tipo [Submit], o navegador envia os parâmetros do formulário (tag <form>) para o URL indicado no atributo [action] da tag <form action="URL">, caso exista. Se esse atributo não existir, os parâmetros do formulário são enviados para o URL que originou o formulário. É esse o caso aqui. O botão [Envoyer] deverá, portanto, dar origem a um pedido do navegador ao URL [http://localhost/form2/formulaire_get.aspx], com a transferência dos parâmetros do formulário. Como a página [formulaire_get.aspx] memoriza o pedido recebido, devemos saber como o cliente transferiu esses parâmetros. Vamos experimentar. Clicamos no botão [Envoyer]. Recebemos a seguinte resposta do navegador:

Image

Esta é a página inicial, mas podemos observar que o valor «URL» mudou no campo «[Adresse]» do navegador. Passou a ser o seguinte:

http://localhost/form2/formulaire_get.aspx?rdMarie=sim&C1=um&C2=dois&txtSaisie=programação+asp.net&txtMdp=unMotDePasse&areaSaisie=as+bases+da%0D%0Aprogramação+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Enviar&secret=uneValeur

Verifica-se que as opções selecionadas no formulário se encontram no URL. Vejamos o conteúdo do ficheiro [request.txt], que memorizou o pedido do cliente:

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

Encontramos uma solicitação HTTP bastante semelhante à que tinha sido feita inicialmente pelo navegador quando este solicitou o documento sem transmitir parâmetros. Existem duas diferenças:

GET URL HTTP/1.1
Os parâmetros do formulário foram adicionados ao final do URL do documento, na forma ?param1=val1&param2=val2&...
Referer
O cliente indica, através deste cabeçalho HTTP, o URL do documento que estava a visualizar quando efetuou o pedido

Vamos analisar mais detalhadamente como os parâmetros foram passados no comando GET URL?param1=valor1&param2=valor2&... HTTP/1.1, em que parami são os nomes dos controlos do formulário web e valeuri os valores que lhes estão associados. Apresentamos abaixo uma tabela com três colunas:

  • coluna 1: apresenta a definição de um controlo HTML do exemplo
  • coluna 2: apresenta a visualização desse controlo num navegador
  • coluna 3: apresenta o valor enviado ao servidor pelo navegador para o controlo da coluna 1, na forma em que aparece na solicitação GET do exemplo
controlo HTML
visualização antes da validação
valor(es) devolvido(s)
<input type="radio" value="sim" name="rdMarie" />Sim
<input type="radio" checked
value="não" name="rdMarie" />Não
rdMarie=sim
- o valor do atributo value do botão
selecionado pelo utilizador.
<input type="checkbox"
value="um" name="C1" />1
<input type="checkbox"
checked value="dois" name="C2" />2
<input type="checkbox"
value="três" name="C3" />3
C1=um
C2=dois
- valores dos atributos value das caixas
marcadas pelo utilizador
<input type="text" maxlength="30" value="algumas
palavras" name="txtSaisie" />
txtSaisie=programação+asp.net
- texto digitado pelo utilizador no campo
de introdução. Os espaços foram substituídos
pelo sinal +
<input type="password"
maxlength="12" size="12"
value="umaPalavra-Passe"
name="txtMdp" />
txtMdp=istoésecreto
- texto digitado pelo utilizador no campo
de introdução. O texto realmente digitado era
"istoé-secreto". O último carácter foi
perdido porque o atributo
maxlength="12" limitava o número de
caracteres a 12.
<textarea name="areaSaisie">
linha1
linha2</textarea>
áreaDeIntrodução=as+bases+de+
da%0D%0A
programação+web
- texto digitado pelo utilizador no campo
de introdução de dados. %OD%OA é o marcador de
fim de linha. Os espaços foram
substituídos pelo sinal +
<select name="cmbValeurs">
<option value="1">opção1
</option>
<option value="2" selected>opção 2
</option>
<option value="3">opção 3
</option>
</select>
cmbValores=3
- valor escolhido pelo utilizador na
lista de seleção única
<select size="3"
name="lstSimple">
<option value="1"
selected>lista1</option>
<option value="2">lista2
</option>
<option value="3">lista3
</option>
<option value="4">lista4
</option>
<option value="5">lista5
</option>
</select>
lstSimple=3
- valor escolhido pelo utilizador na
lista de seleção única
<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
- valores selecionados pelo utilizador na
lista de seleção múltipla
<input type="submit"
value="Enviar"
name="btnEnviar" />
btnEnvoyer=Enviar
- nome e atributo value do botão que
serviu para enviar os dados do formulário
para o servidor
<input type="hidden"
name="secret"
value="umValor" />
 
secret=umValor
- atributo value do campo oculto

Podemos perguntar-nos o que o servidor fez com os parâmetros que lhe foram passados. Na realidade, nada. Ao receber o comando

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

O servidor web transmitiu os parâmetros do URL para os documentos [http://localhost/form2/formulaire_get.aspx] e c.a.d, que constituem o documento que criámos inicialmente. Não escrevemos qualquer código para recuperar e processar os parâmetros que o cliente nos envia. Assim, tudo acontece como se o pedido do cliente fosse simplesmente:

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

É por esta razão que, em resposta ao nosso botão [Envoyer], obtivemos a mesma página que a obtida inicialmente ao solicitar o URL [http://localhost/form2/formulaire_get.aspx] sem parâmetros.

5.3.2. Método POST

O documento HTML está agora configurado para que o navegador utilize o método POST para enviar os valores do formulário ao servidor web. Para tal, copiamos o ficheiro [formulaire_get.aspx] para [formulaire_post.aspx] e alteramos apenas a tag <form> em [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">

Não é necessário alterar o controlador [formulaire_get.aspx.vb], pelo que o mantemos tal como está. Solicitamos o novo documento através do URL [http://localhost/form2/formulaire_post.aspx], preenchemos o formulário tal como no método GET e enviamos os parâmetros para o servidor com o botão [Envoyer]. Recebemos do servidor a seguinte página de resposta:

Image

Assim, obtemos o mesmo resultado que com os métodos GET e c.a.d: a página inicial. É de salientar uma diferença: no campo [Adresse] do navegador, os parâmetros transmitidos não aparecem. Agora, vejamos o pedido enviado pelo cliente e que foi guardado no ficheiro [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

Aparecem novidades na consulta HTTP do cliente:

POST URL HTTP/1.1
a consulta GET foi substituída por uma consulta POST. Os parâmetros já não se encontram nesta primeira linha da consulta. Verifica-se que estão agora colocados a seguir à consulta HTTP, após uma linha em branco. A sua codificação é idêntica à que tinham na consulta GET.
Content-Length
número de caracteres «enviados», c.a.d. O número de caracteres que o servidor web terá de ler após receber os cabeçalhos HTTP para recuperar o documento que o cliente lhe envia. O documento em questão é, neste caso, a lista de valores do formulário.
Content-type
especifica o tipo de documento que o cliente enviará após os cabeçalhos HTTP. O tipo [application/x-www-form-urlencoded] indica que se trata de um documento que contém valores do formulário.

Existem dois métodos para transmitir dados a um servidor web: GET e POST. Será que um método é melhor do que o outro? Vimos que, se os valores de um formulário fossem enviados pelo navegador com o método GET, o navegador exibia no seu campo Adresse o URL solicitado na forma URL?param1=val1&param2=val2&.... Isto pode ser visto como uma vantagem ou uma desvantagem:

  • uma vantagem se se quiser permitir que o utilizador coloque esse URL configurado nos seus favoritos
  • uma desvantagem se não se quiser que o utilizador tenha acesso a determinadas informações do formulário, como, por exemplo, os campos ocultos

Posteriormente, utilizaremos quase exclusivamente o método POST nos nossos formulários.

5.4. Processamento no servidor dos valores de um formulário

5.4.1. Apresentação do exemplo

Agora que estabelecemos a ligação entre a baliza HTML <form method="GET/POST" ...> e a forma como o navegador envia os valores do formulário, sabemos como recuperá-los do lado do servidor. Foi o capítulo anterior que nos deu a resposta:

  • se o método da tag <form> for GET, os valores dos parâmetros serão recuperados na coleção [Request.QueryString]
  • se o método da tag <form> for POST, os valores dos parâmetros «enviados» serão recuperados na coleção [Request.Form]. É necessário aqui fazer uma precisão. A baliza <form> pode especificar, através do atributo [action], o URL de destino do GET ou do POST. Esta URL pode muito bem ser configurada, quer se trate de um GET ou de um POST, na forma action="url?param1=val1&param2=val2&..". Estes parâmetros são então adicionados aos que se encontram entre as balizas <form> e </form> e que serão transferidos para o servidor por meio de um GET ou de um POST. Como fazem parte do URL de destino, serão obtidos na coleção [Request.QueryString], quer se trate de um GET ou de um POST.

Vamos agora criar uma aplicação MVC com duas vistas:

  • a primeira vista é o formulário anterior. Vamos chamá-la de [vue_formulaire].
  • a segunda vista é uma página de informações que lista os valores introduzidos na primeira página. Um link permite regressar ao formulário. Vamos chamar a esta vista [vue_confirmation].

A vista [vue_formulaire] é enviada ao utilizador, que a preenche e valida. Poderia ter este aspeto imediatamente antes da validação:

Image

O utilizador utiliza o botão [Envoyer] para validar os seus dados. Em resposta, recebe a seguinte vista [vue_validation]:

Image

5.4.2. O controlador da aplicação

Vimos no capítulo anterior que podíamos atribuir a função de controlador de uma aplicação MVC ao ficheiro [global.asax], pelo qual passam todos os pedidos dos clientes. Já apresentámos uma aplicação MVC construída desta forma e, aqui, seguimos o modelo de desenvolvimento apresentado nessa altura. O ficheiro [global.asax] terá o seguinte conteúdo:

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

É constituído por uma única linha que faz referência ao controlador localizado no ficheiro [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)
        ' recupera-se a ação a realizar
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' executa-se a ação
        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

O princípio do controlador é o seguinte:

  • espera que, no URL de destino, exista uma cadeia de parâmetros que contenha o parâmetro [action]. Se este estiver ausente, trata-se como se tivéssemos [action=init] na cadeia de parâmetros.
  • Apenas duas ações são reconhecidas:
    • init: é enviado ao cliente o formulário pré-preenchido
    • validação: é apresentada ao cliente a página que confirma os dados introduzidos
  • Se a ação não for nenhuma das anteriores, trata-se como se tivéssemos [action=init]. Também se poderia apresentar uma página de erro.

5.4.3. Processamento da ação «init»

Quando o controlador processa a ação «init», deve gerar um formulário pré-preenchido. Cabe à página [formulaire.aspx] realizar essa tarefa. O seu código é o seguinte:


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

Encontramos o código HTML do formulário analisado anteriormente, com algumas diferenças. O código da baliza <form> foi alterado:


        <form name="formulaire" method="post" action="?action=validation">
  • post: os valores introduzidos pelo utilizador e posteriormente enviados para o servidor quando o botão do tipo [submit] for utilizado serão enviados através do método HTTP POST
  • ação: a sintaxe action="url" serve para indicar a URL para a qual os valores do formulário devem ser enviados. Esta URL pode incluir uma cadeia de parâmetros com o formato param1=val1&param2=val2&... É isso que se faz aqui, onde passamos o parâmetro [action=validation] para indicar ao controlador a ação que deve realizar. Note-se que esta cadeia de parâmetros não é precedida por um endereço web. O navegador enviará, então, os parâmetros do formulário para o endereço que lhe forneceu esse formulário. No nosso exemplo apresentado acima, esse endereço é [http://localhost/mvcform1]. O navegador fará, portanto, uma solicitação [POST /mvcform1?action=validation] à máquina [localhost].

Foram adicionados botões para permitir que o utilizador desmarque os elementos das listas [lstSimple] e [lstMultiple]:

Image

Isto traduz-se no seguinte código HTML:


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

Um clique num botão [Raz] faz com que todos os elementos da lista a que está associado sejam desmarcados. Tomemos como exemplo a lista [lstMultiple]. Ao clicar no botão [Raz] correspondente, é executada a função JavaScript [raz(lstMultiple)]. Recorde-se que o código JavaScript de um documento HTML apresentado por um navegador é executado por esse mesmo navegador e não pelo servidor. O JavaScript é uma linguagem muito completa que permite conferir um aspeto dinâmico às páginas sem a intervenção do servidor. A função [raz] é a seguinte:

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

Esta função recebe um parâmetro que é um objeto JavaScript que representa uma lista HTML. Este objeto possui propriedades e métodos. Uma das suas propriedades é [selectedIndex], cujo valor é o número da primeira opção selecionada na lista HTML. Se não houver nenhuma, esta propriedade assume o valor -1. Por outro lado, atribuir um valor a esta propriedade equivale a selecionar um novo elemento na lista HTML e atribuir-lhe o valor -1 equivale a não ter nenhum elemento selecionado. É isso que se faz aqui.

Por fim, note-se que o código de apresentação [formulaire.aspx] não é acompanhado por um controlador [formulaire.aspx.vb]. Com efeito, não há nenhuma parte dinâmica gerada pelo servidor no documento HTML, pelo que não há necessidade de ter um controlador.

5.4.4. Processamento da ação de validação

Quando o controlador processa a ação «validação», deve gerar uma página que liste os valores introduzidos pelo utilizador. Cabe à página [validation.aspx] realizar essa tarefa. Visualmente, a página apresenta-se da seguinte forma:

Image

O seu código HTML é o seguinte:


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

As partes dinâmicas <%=variável%> do documento são calculadas pelo controlador [validation.aspx.vb] associado:


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
        'recuperam-se os parâmetros enviados
        rdMarie = getValue("rdMarie")
        C1 = getValue("C1")
        C2 = getValue("C2")
        C3 = getValue("C3")
        txtSaisie = getValue("txtSaisie")
        txtMdp = getValue("txtMdp")
        areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
        cmbValeurs = getValue("cmbValeurs")
        lstSimple = getValue("lstSimple")
        lstMultiple = getValue("lstMultiple")
        secret = getValue("secret")
    End Sub

    Private Function getValue(ByVal champ As String) As String
        ' recupera o valor do campo [champ] da solicitação enviada
        ' alguma coisa?
        If Request.Form(champ) Is Nothing Then Return ""
        ' recupera o(s) valor(es) do campo
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function

End Class

O cálculo dos valores a apresentar é efetuado no procedimento [Form_Load]. O valor de um campo «enviado» é obtido através da função getValue(C), em que C é o nome do campo. Os pontos-chave desta função são os seguintes:

  • se C não estiver na cadeia de parâmetros lançada, então retorna-se a cadeia vazia como valor de C
  • caso contrário, obtém-se a matriz de valores do campo C através de [Request.Form.GetValues(C)]. Estes valores são concatenados numa cadeia de caracteres sob a forma [val1][val2]...[valn], em que [vali] é o valor n.º i do campo C

O campo [areaSaisie] é tratado de forma específica. O seu valor é enviado pelo navegador na forma areaSaisie=linha1\r\nlinha2\r\n... onde \r é o carácter de código ASCII 13 (retorno de carro) e \n é o carácter de código ASCII 10 (salto de linha). A função getValue(areaSaisie) é, portanto, a cadeia «linha1\r\nlinha2\r\n...». Esta cadeia é dividida em linhas pelo método [Regex.Split]. Obtém-se então um tabular de cadeias {linha1,linha2,...}. Este tabular é transformado na cadeia «linha1,linha2,...» pelo método [String.Join]. É esta última cadeia que será apresentada como valor do campo [areaSaisie]. O objetivo aqui era mostrar como se podiam obter as diferentes linhas de um campo HTML do tipo [TextArea].

5.4.5. Testes

Colocamos todos os ficheiros (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) numa pasta <application-path>. Iniciamos o servidor Cassini com os parâmetros (<application-path>,/mvcform1). Criamos na pasta <application-path> um ficheiro [default.aspx] vazio e, em seguida, acedemos à URL [http://localhost/mvcform1]. Como [/mvcform1] é o caminho virtual de uma pasta e não de um documento, o servidor web irá apresentar o documento [default.aspx], caso este exista. É por isso que o criámos. Antes de o apresentar, o script [global.asax] será executado e, por fim, fará com que a página [formulaire.aspx] seja apresentada. É por isso que o ficheiro [default.aspx] pode estar vazio.

Suponhamos que o formulário validado seja o seguinte:

Image

Ao utilizar o botão [Envoyer], é apresentada a seguinte página:

Image

Repare, em primeiro lugar, no URL da resposta: [http://localhost/mvcform1/?action=validation]. Trata-se do URL do atributo [action] da baliza <form> do formulário [formulaire.aspx]:


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

Vamos analisar, um a um, os valores obtidos para os diferentes campos do formulário:

campo
valor
HTML
comentários
rdMarie
sim
<input type="radio" value="sim"
name="rdMarie">Sim
<input type="radio" checked
value="não" name="rdMarie">Não
o valor obtido é o atributo [value] do botão selecionado
C1
um
<input type="checkbox"
value="um" name="C1">1
idem
C2
dois
<input type="checkbox"
marcado value="dois" name="C2">2
idem
C3
 
<input type="checkbox"
value="três" name="C3">3
este botão não foi marcado pelo utilizador. O seu valor não foi, portanto, enviado pelo navegador. No código, a condição [Request.Form("C3") is Nothing] foi, portanto, verdadeira.
txtSaisie
Programação
asp.net
<input type="text"
... name="txtSaisie">
o valor obtido é o texto presente no campo de introdução no momento da validação
txtMdp
mdp
<input type="password"
...name="txtMdp">
idem
areaSaisie
noções básicas de
programação web
<textarea name="areaSaisie">
...</textarea>
idem
cmbValeurs
3
<select name="cmbValeurs">
...
<option value="3">opção 3</option>
</select>
o valor obtido é o atributo [value] da opção selecionada
lstSimple
3
<select size="3" name="lstSimple">
....
<option value="3">lista3</option>
...
</select>
idem
lstMultiple
2 4
<select multiple size="3" name="lstMultiple">
...
<option value="2">multiple2
</option>
...
<option value="4">multiple4
</option>
...
</select>
os valores obtidos são os dos atributos [value] das opções selecionadas
secreto
uneValeur
<input type="hidden"
name="secret" value="umValor">
o valor obtido é o atributo [value] do campo oculto

Agora, vamos analisar as listas. Suponhamos que, no momento da validação, o estado do formulário seja o seguinte:

Image

  • a opção [choix1] está selecionada no comboBox
  • nenhuma opção está selecionada nas outras duas listas. Utilizámos os botões [Raz] para obter este resultado.

Eis a página apresentada após a validação:

Image

Quando não é selecionado nenhum valor numa lista, o navegador não envia nenhum parâmetro para essa lista. No código de [validation.aspx.vb], as expressões [Request.Form("lstSimple")] e [Request.Form("lstMultiple")] são, portanto, iguais à constante [Nothing], daí o resultado apresentado acima.

5.5. Manter o estado de uma página

5.5.1. Manter o estado de uma página com uma sessão

Duplicamos toda a aplicação anterior numa nova pasta. Adicionamos um link na página [validation.aspx] que permite ao utilizador regressar ao formulário:

Image

A alteração a efetuar na página [validation.aspx] consiste na adição do link:


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

O atributo [href] do link tem como valor um URL parametrizado com o único parâmetro [action=formulaire], permitindo que o servidor saiba que deve apresentar o formulário tal como estava quando foi validado. Existe, portanto, uma diferença em relação à ação [init], que apresenta um formulário predefinido. A URL parametrizada [?action=formulaire] não tem, na verdade, uma URL. Esta será, portanto, a mesma que permitiu a apresentação da página de validação. Se nos lembrarmos do estudo anterior, esta é a URL da pasta da aplicação. A solicitação passará, portanto, pelo controlador. Este deve agora processar a ação [formulaire]. O código de [global.asax.vb] é alterado da seguinte forma:


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' recupera-se a ação a realizar
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' executa-se a ação
        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

No caso de a ação ser «formulário», basta enviar o pedido para a página [formulaire.aspx]. Sabemos que esta página apresenta um formulário predefinido no qual não há nenhuma parte variável. Por conseguinte, esta página não pode apresentar o formulário com os valores que tinha quando foi validado. O objetivo aqui é destacar este ponto. Se todos os ficheiros da aplicação tiverem sido colocados em <application-path>, iniciamos o Cassini com os parâmetros (<application-path>,/mvcform2) e, em seguida, acedemos à URL [http://localhost/mvcform2]. Obtemos a seguinte página (vista parcial):

Image

Preenchemos o formulário da seguinte forma e, em seguida, validamo-lo:

Image

Obtenemos a seguinte página de confirmação:

Image

Utilizamos o link [Retour au formulaire] presente (mas não representado) na página acima. Obtemos a seguinte resposta do servidor:

Image

Constatamos que:

  • a URL solicitada contém, de facto, o parâmetro action=formulário, tal como pretendido
  • o formulário apresentado perdeu os valores introduzidos.

Sabemos por que razão não recuperamos os valores introduzidos. Se analisarmos o código do documento [formulaire.aspx], verificamos que tudo é estático e que, por isso, é obrigado a apresentar sempre a mesma página. É evidente que precisamos de tornar este código dinâmico. Terá de apresentar os valores validados pelo utilizador. Mas onde os guardar?

Recordemos a regra de ouro do protocolo sem estado HTTP:

  • a URL [http://localhost/mvcform2] é solicitada — recebe-se uma resposta. Foi estabelecida uma ligação TCP-IP entre o cliente e o servidor no início do pedido e encerrada no final da resposta.
  • O utilizador introduz e, em seguida, valida os dados. A URL [http://localhost/mvcform2/?action=validation] é solicitada — é recebida uma resposta. Uma nova ligação TCP-IP foi aberta e, posteriormente, encerrada entre os dois parceiros.
  • O utilizador utiliza o link [Retour au formulaire]. A URL [http://localhost/mvcform2/?action=formulaire] é solicitada — é recebida uma resposta. Uma nova ligação TCP-IP foi novamente aberta e, em seguida, encerrada entre os dois parceiros.

Os ciclos de pedido-resposta são independentes uns dos outros, porque cada um deles utiliza uma nova ligação TCP-IP. Quando uma aplicação cliente-servidor utiliza uma única ligação TCP-IP para uma sequência de trocas, o servidor pode identificar um cliente através da sua ligação. Pode, assim, memorizar informações que irá associar a uma ligação específica e, dessa forma, acompanhar as trocas. Quando as trocas ocorrem em ligações diferentes, o servidor não consegue identificar um cliente a partir de uma ligação. É necessário outro meio. Apresentámos um deles no capítulo anterior: o mecanismo de sessão. Este permite que os ciclos de pedido-resposta armazenem informações num objeto [Session] acessível a todos os ciclos sucessivos.

Agora que temos uma aplicação MVC com sessão, já não podemos utilizar o ficheiro [global.asax] como controlador, tal como foi demonstrado no capítulo anterior. A função de controlador da aplicação deve ser desempenhada por uma página específica dedicada a isso. Neste caso, será a página [main.aspx]. Procederemos da seguinte forma:

  • quando o utilizador validar os seus dados (ação=validação), o controlador [main.aspx.vb] irá armazená-los na sessão atual antes de apresentar a página de validação.
  • quando for necessário apresentar o formulário com os valores introduzidos (ação=formulário), o controlador [main.aspx.vb] irá recuperá-los da sessão e colocá-los no contexto antes de apresentar o formulário.

5.5.2. O novo controlador de aplicação

O controlador de aplicação é composto pelos dois ficheiros [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
        ' recupera-se a ação a realizar
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' executa-se a ação
        Select Case action
            Case "init"
                ' exibe-se o formulário pré-preenchido
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
            Case "validation"
                ' exibe-se a página de confirmação após guardar os valores enviados na sessão
                Session.Item("formulaire") = Request.Form
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                ' exibe-se o formulário com os valores obtidos da sessão
                Context.Items("formulaire") = Session.Item("formulaire")
                Server.Transfer("formulaire.aspx", True)
            Case Else
                ' exibe o formulário pré-preenchido
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub

    Private Function initForm() As NameValueCollection
        ' inicializa-se o formulário
        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

Encontramos aqui a essência da estrutura do controlador de aplicação analisado anteriormente, com as seguintes diferenças:

  • o trabalho do controlador é realizado no procedimento [Form_Load]
  • no caso da ação [validation], os valores do formulário presentes em [Request.Form] são armazenados na sessão associada à chave «formulário». Em seguida, a execução é transferida para a página [validation.aspx], que apresentará esses valores.
  • Para as restantes ações, a execução é, em todos os casos, transferida para a página [formulaire.aspx]. Esta página espera, no seu contexto, uma chave «formulário» que será associada a um objeto do tipo [Request.form], c.a.d ou do tipo [NameValueCollection]. Este objeto deve conter a coleção de valores dos campos do formulário.
  • No caso de a ação ser [init] ou uma ação não reconhecida, a coleção de valores é construída arbitrariamente pela função [initForm].
  • No caso de a ação ser [formulaire], esta coleção é a coleção [Request.Form] que tinha sido colocada na sessão pela ação [validation]

5.5.3. O novo formulário

Como a aplicação já não apresenta o mesmo conteúdo no formulário, este deve ser gerado dinamicamente. A nova página [formulaire.aspx] passa a ter o seguinte aspeto:


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

Vamos comentar as variáveis dinâmicas que aparecem no código HTML:

variável
função
rdouichecked
terá o valor «checked» se o botão de opção [oui] tiver de ser marcado; caso contrário, terá o valor «»
rdnonchecked
o mesmo se aplica ao botão de opção [non]
c1checked
o mesmo se aplica à caixa de seleção [C1]
c2checked
o mesmo se aplica à caixa de seleção [C2]
c3checked
o mesmo se aplica à caixa de seleção [C3]
txtSaisie
o texto a inserir no campo [txtSaisie]
txtMdp
o texto a inserir no campo [txtMdp]
areaSaisie
o texto a inserir no campo [areaSaisie]
cmbValeursOptions
o texto HTML das opções da lista de seleção [cmbValeurs]
lstSimpleOptions
o texto HTML das opções da lista de seleção [lstSimple]
lstMultipleOptions
o texto HTML das opções da lista de seleção [lstMultiple]
  

Os valores destas variáveis são calculados pelo controlador da página [formulaire.aspx.vb]:


Imports Microsoft.VisualBasic
Imports System.Collections.Specialized

Public Class formulaire
    Inherits System.Web.UI.Page

    ' campos fixos do formulário
    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"}

    ' campos dinâmicos do formulário
    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
        ' recupera-se a solicitação anterior na sessão
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If
        ' prepara-se a página a apresentar
        ' botões de opção
        rdouichecked = ""
        rdnonchecked = "checked"
        If isEqual(form("rdMarie"), "oui") Then
            rdouichecked = "checked"
            rdnonchecked = ""
        End If
        ' caixas de seleção
        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"
        ' campos de introdução de dados
        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
        ' listas
        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
        ' gera o código HTML das opções de uma baliza <select>
        ' valores: tabela de valores das opções da baliza
        ' designações: tabela das designações das opções da baliza
        ' seleções: opções a selecionar
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' percorre-se a lista de valores das opções
        For iValeur = 0 To valeurs.Length - 1
            ' verifica-se se o valor atual deve ser selecionado
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' insere-se o código HTML da opção
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' retorna o resultado
        Return toString
    End Function

    Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
        ' retorna «verdadeiro» se o campo for igual ao valor
        If champ Is Nothing OrElse champ.ToString <> valeur Then
            Return false
        Else
            Return true
        End If
    end function
End Class

Quando a página [formulaire.aspx] começa a ser executada, encontra no seu contexto uma chave «formulário» associada ao conjunto de valores dos campos que deve apresentar.


         ' recupera-se a consulta anterior na sessão
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If

Pode-se questionar por que razão se verifica se [Context.Items("formulaire")] existe. De facto, o controlador atribui um valor a este objeto em todos os casos. No entanto, nada impede que o cliente solicite diretamente a página [formulaire.aspx] sem passar pelo controlador. Se isso acontecer, o código anterior funcionará com uma coleção de valores vazia, mas não ocorrerá qualquer «falha».

O código analisa a coleção de valores que recebeu para calcular todas as variáveis dinâmicas da página HTML que lhe está associada. Embora seja extenso, este código não é especialmente complicado e deixamos que o leitor o explore por si próprio, para não sobrecarregar esta explicação. No entanto, vamos debruçar-nos sobre a forma de gerar o código HTML a partir das três listas do tipo [select]. Este código é gerado pela seguinte função:

    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
         ' retorna o código HTML das opções de uma baliza <select>
         ' valores: tabela dos valores das opções da baliza
         ' designações: tabela das designações das opções da baliza
         ' seleções: opções a selecionar
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
         ' percorre-se a lista de valores das opções
        For iValeur = 0 To valeurs.Length - 1
             ' verifica-se se o valor atual deve ser selecionado
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
             ' insere-se o código HTML da opção
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
         ' retorna-se o resultado
        Return toString
    End Function

Recorde-se que as opções de uma baliza <select> correspondem ao seguinte código HTML:

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

Para cada opção, há, portanto, três informações a gerar:

  • o valor da opção no atributo [value]
  • o texto da opção entre as tags <option> e </option>
  • a palavra-chave [selected], caso a opção deva ser selecionada na lista

Para gerar estas três informações para cada uma das opções, a função [getOptions] recebe três valores:

  1. a tabela de valores das opções em [valeurs]
  2. a tabela de textos das opções em [libelles]
  3. a tabela de valores a selecionar em [sélections]

5.5.4. A página de validação

A página de validação permanece inalterada:

[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
        'recuperam-se os parâmetros enviados
        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")
        ' guardam-se na sessão
        'Session("formulário") = Request.Form
    End Sub

    Private Function getValue(ByVal champ As String) As String
        ' recupera o valor do campo [champ] da solicitação enviada
        ' alguma coisa?
        If Request.Form(champ) Is Nothing Then Return ""
        ' recupera o(s) valor(es) do campo
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function
End Class

5.5.5. Os testes

Os ficheiros [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] são colocados em <application-path> e o Casini é iniciado com os parâmetros (<application-path>,/mvcform3). Em seguida, acedemos à URL [http://localhost/mvcform3/main.aspx]. Obtemos o formulário pré-inicializado:

Image

Preenchemos o formulário da seguinte forma:

Image

Utilizamos o botão [Envoyer] acima. Obtemos a seguinte resposta do servidor:

Image

Utilizamos o link [Retour au formulaire] acima para voltar ao formulário. Obtemos a seguinte resposta nova:

Image

Encontramos, de facto, o formulário tal como o validámos.

5.5.6. Conclusão

O exemplo anterior mostrou-nos que é possível manter o estado de uma página ao longo dos ciclos de pedido-resposta entre o cliente e o servidor. No entanto, esta tarefa não é trivial. Veremos num capítulo posterior que, com o ASP.NET, é possível deixar que o servidor restabeleça por si próprio o estado de uma página.