Skip to content

5. Gestão da Interface do Utilizador

5.1. Introdução

Na relação cliente-servidor na Web, o cliente envia informações para o servidor na forma de uma sequência de parâmetros [param1=val1&param2=val2&...]. Nos nossos exemplos anteriores, na maioria das vezes construímos essa sequência manualmente, solicitando URLs do tipo [http://localhost/appli? param1=val1&param2=val2&...]. Na realidade, a informação que o cliente envia ao servidor provém de formulários que o utilizador preencheu. Neste capítulo, exploramos como construir esses formulários. Apresentamos também a ferramenta WebMatrix, que nos permitirá projetar interfaces de utilizador. A instalação desta ferramenta é descrita nos apêndices.

5.2. A linguagem HTML

5.2.1. Um exemplo

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

  • uma tabela
  • uma imagem
  • um link

Image

Inicie o [WebMatrix] e selecione a opção [Ficheiro/Novo Ficheiro]:

Image

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

Image

O modo [Design] permite-lhe utilizar a paleta de componentes HTML fornecida 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-lhe construir o documento HTML utilizando um editor de texto. Isto requer conhecimento da sintaxe HTML. No separador [HTML], foi gerado um esqueleto de documento:

Image

A janela [HTML] é muito útil para quem não está familiarizado com HTML. Cria-se o documento na janela [Design] e verifica-se o código HTML gerado na janela [HTML]. Desta forma, vai-se dominando gradualmente o HTML e passa-se a trabalhar rapidamente apenas com o editor de texto, sem depender do modo [Design]. Vamos agora demonstrar como criar o documento HTML apresentado no início desta secção. Estamos a trabalhar na janela [Design]. Primeiro, introduzimos a primeira linha de texto diretamente:

Image

  • adicionamos o componente [Linha Horizontal] a partir da paleta de componentes:

Image

  • adicionamos o componente [Tabela]:

Image

  • colocamos o cursor na terceira linha da tabela para a eliminar utilizando a opção [HTML/Editar Tabela/Eliminar Linha da Tabela]. Em seguida, introduzimos o texto pretendido em cada célula:

Image

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

Image

  • A célula é representada pela tag HTML <TD>. São-nos, portanto, mostradas as propriedades da tag <TD>. Concentramo-nos na tabela, que é um objeto que contém a célula. Clicamos na lista suspensa (clicar para ver os elementos HTML pai) acima para selecionar o objeto <TABLE>:

Image

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

Image

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

Image

  • Agora colocamos o texto que precede a imagem:

Image

  • depois a imagem, clicando duas vezes no componente [image] na 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 [aqui] num link para o URL [http://istia.univ-angers.fr]. Para isso, selecionamo-lo e, em seguida, escolhemos a opção [HTML/Inserir Hiperligação]:

Image

  • Obtemos o seguinte resultado:

Image

  • Estamos quase lá. Vamos dar uma olhadela ao 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 para resolver. Primeiro, gostaríamos de dar um título ao nosso documento. O [WebMatrix] não permite fazer isso no modo [Design]. No separador [HTML], substituímos a secção <head>..</head> pelo seguinte:

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

Além disso, gostaríamos que o texto [HTML - 1] aparecesse com uma fonte maior. A tag <Hi>text</Hi> permite definir o tamanho do texto, com "i" variando de 1 a 6, do maior para o menor. Aqui, vamos usar H2. A tag

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

torna-se:

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

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

Image

Resta apenas testá-la utilizando a opção [View/Start] ou [F5]. O [WebMatrix] solicita algumas informações para iniciar o servidor web [Cassini]:

Image

Podemos aceitar os valores predefinidos. O servidor [Cassini] é iniciado e a nossa página é apresentada num navegador:

Image

Por curiosidade, podemos verificar quais os parâmetros que foram utilizados para iniciar o [Cassini]:

Image

Já abordámos os conceitos básicos da criação de uma página HTML com o [WebMatrix]. Recomendamos aos leitores que criem outras páginas HTML e verifiquem o código HTML gerado em cada ocasião. Aos poucos, conseguirão criar uma página sem recorrer ao modo [Design]. Um documento HTML tem, geralmente, a seguinte estrutura:

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

Todo o documento está entre as tags <html>...</html>. É composto por duas partes:

<head>...</head>: Esta é a parte não exibível do documento. Fornece informações ao navegador que irá exibir o documento. Contém frequentemente a tag <title>...</title>, que define o texto que aparecerá na barra de título do navegador. Pode também conter outras tags, incluindo aquelas que definem as palavras-chave do documento, que são depois utilizadas pelos motores de busca. Esta secção pode ainda conter scripts, geralmente escritos em JavaScript ou VBScript, que serão executados pelo navegador.

<body attributes>...</body>: Esta é a secção que será exibida pelo navegador. As tags HTML contidas nesta secção indicam ao navegador o layout visual «desejado» para o documento. Cada navegador interpreta estas tags à sua maneira. Como resultado, dois navegadores podem exibir o mesmo documento web de forma diferente. Este é geralmente um dos desafios enfrentados pelos 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>
HTML
Etiquetas HTML e exemplos
título do documento
<title>HTML1</title>
HTML1 aparecerá na barra de título do navegador quando o documento for exibido
barra horizontal
<horizontal> : exibe uma linha horizontal
tabela
<attributos da tabela>....</table> : para definir a tabela
<tr atributos>... : para definir uma linha
<td atributos>... : para definir uma célula
exemplos:
<table border="1">...: o atributo border define a espessura da borda da tabela
<td align="center" width="200">célula(1,2) : define uma célula cujo conteúdo será célula(1,2). Este conteúdo será centralizado horizontalmente (align="center"). A célula terá uma largura de 200 píxeis (width="200")
imagem
<img src="univ01.gif" />: define uma imagem cujo ficheiro de origem é univ01.gif no servidor web (src="univ01.gif"). Esta ligação encontra-se num documento web acessível através do URL http://localhost/exemple1.htm. Por conseguinte, o navegador irá solicitar o URL http://localhost/univ01.gif para recuperar a imagem aqui referenciada.
link
<a href="http://istia.univ-angers.fr">aqui: faz com que o texto «aqui» funcione como um link para o URL http://istia.univ-angers.fr.

Neste exemplo simples, podemos ver que, para construir o documento na íntegra, o navegador deve fazer duas solicitações ao servidor:

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

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

5.2.2. Criação de um formulário

O objetivo de um formulário HTML é 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 como um documento HTML. O navegador apresenta o formulário ao utilizador, que o preenche e o submete utilizando um botão com essa função. O navegador transmite então os valores introduzidos ao servidor para processamento. Veremos que ele não envia o formulário inteiro de volta para o servidor, mas apenas os valores inseridos. O exemplo a seguir mostra um formulário web também criado com o 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>

O mapeamento entre elementos visuais e tags HTML é o seguinte:

Controlo visual
Tag HTML
form
<form name="form" method="post">
campo de entrada
<input type="text" maxlength="30" value="algumas palavras" name="txtInput" />
campo de entrada oculto
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" />
campo de entrada multilinha
<textarea name="inputArea">linha1
linha2</textarea>
botões de opção
<input type="radio" value="yes" name="rdMarie" />Sim
<input type="radio" checked value="no" name="rdMarie" />Não
caixas de seleção
<input type="checkbox" value="one" name="C1" />1
<input type="checkbox" checked value="two" name="C2" />2
<input type="checkbox" value="três" name="C3" />3
Lista suspensa
<select name="cmbValeurs">
<option value="1">opção1</option>
<option value="2" selected>opção2</option>
<option value="3">opção3</option>
</select>
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>
lista de seleção múltipla
<select multiple size="3" name="lstMultiple">
<option value="1" selected>múltipla1</option>
<option value="2">múltipla2</option>
<option value="3" selected>multiple3</option>
<option value="4">múltiplo4</option>
<option value="5">multiple5</option>
</select>
campo oculto
<input type="hidden" name="secret" value="aValue" />
botão de envio
<input type="submit" value="Enviar" name="submitButton" />
botão de reiniciar
<input type="reset" value="Redefinir" name="btnReset" runat="server" />
botão
<input onclick="clear()" type="button" value="Limpar" name="btnClear" />

Vamos rever estes diferentes controlos.

5.2.2.1. O

formulário
<form name="form" method="post">
HTML
<form name="..." method="..." action="...">...</form>
atributos
name="formexample": nome do formulário
method="..." : método utilizado pelo navegador para enviar os valores recolhidos no formulário para o servidor web
action="..." : URL para a qual os valores recolhidos no formulário serão enviados.
Um formulário web é delimitado pelas tags <form>...</form>. O formulário pode ter um nome (name="xx"). Isto aplica-se a todos os controlos presentes 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 informações introduzidas pelo utilizador através do teclado ou do rato e enviá-las para um URL de servidor web. Qual? Aquele referenciado no atributo action="URL". Se este atributo estiver em falta, as informações serão enviadas para o URL do documento no qual o formulário se encontra. Como é que um cliente web envia informações (os dados contidos no formulário) para um servidor web? Já abordámos este tema em detalhe. Pode utilizar dois métodos diferentes, chamados POST e GET. O atributo method="método" da tag <form>, onde método é definido como GET ou POST, indica ao navegador qual 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 entrada

Image

campo de entrada
<input type="text" maxlength="30" value="algumas palavras" name="txtInput" />
<input type="password" maxlength="12" size="12" value="aPassword" name="txtMdp" />
Etiqueta HTML
<input type="..." name="..." size=".." value="..">
A tag input existe para vários controlos. É o atributo type que distingue estes diferentes controlos uns dos outros.
atributos
type="text": especifica que este é um campo de entrada de texto
type="password": os caracteres no campo de entrada são substituídos por asteriscos (*). Esta é a única diferença em relação a um campo de entrada normal. Este tipo de controlo é adequado para introduzir 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 para 30 — o navegador é responsável por aplicar este atributo
name="txtInput": nome do controlo
value="algumas palavras": texto que será exibido no campo de entrada.

5.2.2.3. Campo de entrada multilinha

Image

campo de entrada multilinha
<textarea name="inputArea">linha1
linha2</textarea>
Tag HTML
<textarea ...>texto</textarea>
exibe um campo de entrada multilinha com texto inicial no interior
atributos
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

botões de opção
<input type="radio" value="yes" name="rdMarie" />Sim
<input type="radio" checked value="no" name="rdMarie" />Não
Etiqueta HTML
<input type="radio" attribute2="value2" ..../>texto
exibe um botão de opção com texto ao lado.
atributos
name="rdMarie": nome do controlo. Os botões de opção com o mesmo nome formam um grupo de botões mutuamente exclusivos: apenas um deles pode ser selecionado.
value="value": valor atribuído ao botão de opção. Não confunda este valor com o texto exibido ao lado do botão de opção. O texto serve apenas para fins de 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.5. Caixas de seleção

caixas de seleção
<input type="checkbox" value="one" name="C1" />1
<input type="checkbox" checked value="two" name="C2" />2
<input type="checkbox" value="três" name="C3" />3

Image

Etiqueta HTML
<input type="checkbox" attribute2="value2" ..../>texto
exibe uma caixa de seleção com texto ao lado.
atributos
name="C1": nome do controlo. As caixas de seleção podem ou não ter o mesmo nome. As caixas de seleção com o mesmo nome formam um grupo de caixas de seleção associadas.
value="valor": valor atribuído à caixa de seleção. Não confunda este valor com o texto exibido ao lado do botão de opção. O texto serve apenas para fins de 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="cmbValues">
<option value="1">opção1</option>
<option value="2" selected>opção2</option>
<option value="3">Opção 3</option>
</select>

Image

Etiqueta HTML
<select size=".." name="..">
<option [selected="selected"] [value="value"]>texto</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
name="cmbValues": nome do controlo.
size="1": número de itens visíveis da lista. size="1" torna a lista equivalente a uma caixa combinada. Este é o valor predefinido se o atributo [size] estiver em falta.
selected="selected": se este atributo estiver presente para um item da lista, esse item aparece selecionado na lista. No nosso exemplo acima, o item da lista "choice2" aparece como o item selecionado na caixa combinada quando é exibido pela primeira vez.
value="value": define o valor a enviar para o servidor se o item for selecionado. Se este atributo estiver em falta, o texto associado à opção é enviado para o servidor.

5.2.2.7. Lista de seleção única

lista de seleção única
<select size="3" name="lstSimple">
<option value="1" selected>list1</option>
<option value="2">lista2</option>
<option value="3">lista3</option>
<option value="4">lista4</option>
<option value="5">lista5</option>
</select>

Image

Tag HTML
<select size=".." name="..">
<option [selected] [value="value"]>...</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
os mesmos que para a lista suspensa que exibe apenas um item. Este controlo difere da lista suspensa anterior apenas no seu atributo size>1.

5.2.2.8. Lista de seleção múltipla

lista de seleção múltipla
<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

Etiqueta HTML
<select size=".." name=".." multiple>
<option [selected] ] [value="value"]>...</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
multiple: permite a seleção de vários itens na lista. No exemplo acima, os itens list1 e list3 estão ambos selecionados.

5.2.2.9. Botão

botão
<input onclick="clear()" type="button" value="Limpar" name="btnClear" />

Image

Etiqueta HTML
<input type="button" value="..." name="..." onclick="clear()" ....>
atributos
type="button": define um controlo de botão. Existem dois outros tipos de botões: submit e reset.
value="Limpar": o texto exibido no botão
onclick="function()": permite definir uma função a ser executada quando o utilizador clica no botão. Esta função faz parte dos scripts definidos no documento web apresentado. A sintaxe acima é sintaxe JavaScript. Se os scripts forem escritos em VBScript, escrever-se-ia onclick="function" sem os parênteses. A sintaxe permanece a mesma se for necessário passar parâmetros para a função: onclick="function(val1, val2,...)"
No nosso exemplo, clicar no botão «Limpar» chama a seguinte função JavaScript:

        <script language="javascript">
        função clear(){
            alert("Clicou no botão [Limpar]");
        }
        </script>
A função clear exibe uma mensagem:

5.2.2.10. Botão Enviar

Botão Enviar
<input type="submit" value="Submeter" name="btnSubmit" />

Image

Etiqueta HTML
<input type="submit" value="Enviar" name="btnSend">
atributos
type="submit": define o botão como um botão para enviar dados do formulário para o servidor web. Quando o utilizador clica neste botão, o navegador envia os dados do formulário para o URL definido no atributo action da tag <form>, utilizando o método definido pelo atributo method dessa mesma tag.
value="Submit": o texto exibido no botão

5.2.2.11. Botão de reinicialização

botão de reinicialização
<input type="reset" value="Reset" name="btnReset" runat="server" />

Image

Tag HTML
<input type="reset" value="Redefinir" name="btnReset">
atributos
type="reset": define o botão como um botão de reinicialização do formulário. Quando o utilizador clica neste botão, o navegador restaura o formulário para o estado em que foi recebido.
value="Reset": o texto exibido no botão

5.2.2.12. Campo oculto

campo oculto
<input type="hidden" name="secret" value="aValue" />
Etiqueta HTML
<input type="hidden" name="..." value="...">
atributos
type="hidden": especifica que este é um campo oculto. Um campo oculto faz parte do formulário, mas não é apresentado ao utilizador. No entanto, se o utilizador solicitar ao seu navegador que apresente o código-fonte, verá a presença da tag <input type="hidden" value="..."> e, consequentemente, o valor do campo oculto.
value="aValue": valor do campo oculto.
Qual é o objetivo do campo oculto? Permite que o servidor web retenha informações entre as solicitações de um cliente. Considere uma aplicação de compras online. O cliente compra um item inicial art1 na quantidade q1 na primeira página de um catálogo e, em seguida, passa para uma nova página no catálogo. Para lembrar que o cliente comprou q1 itens de art1, o servidor pode colocar estas duas informações num campo oculto no formulário web da nova página. Nesta nova página, o cliente compra q2 unidades do item art2. Quando os dados deste segundo formulário forem enviados ao servidor, este não só receberá a informação (q2,art2), mas também (q1,art1), que também faz parte do formulário como um campo oculto que não pode ser modificado pelo utilizador. O servidor web colocará então as informações (q1,art1) e (q2,art2) num novo campo oculto e enviará uma nova página do catálogo. E assim por diante.

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

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

  • uma solicitação HTTP GET: url?param1=va1&param2=val2&....
  • uma solicitação HTTP POST seguida de um documento contendo a sequência de parâmetros param1=va1&param2=val2&....

O navegador utilizará um destes dois métodos, dependendo se o atributo [method] da tag [form] estiver definido como GET ou POST. É isso que vamos demonstrar agora. A página que vimos anteriormente é uma página estática. Para aceder aos cabeçalhos HTTP enviados pelo navegador que solicita este documento, vamos convertê-la numa página dinâmica para um servidor web .NET (IIS ou Cassini). O código estático anterior é colocado num ficheiro chamado [form_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 [form_get.aspx.vb]:


Public Class formulaire_get
    Inherits System.Web.UI.Page
 
    Private Sub Page_Init(ByVal Sender As Object, ByVal e As System.EventArgs) Handles MyBase.Init
        ' saves the current query in request.txt of the page folder
        Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
        Me.Request.SaveAs(requestFileName, True)
    End Sub
End Class

Sempre que o documento [form_get.aspx] for chamado, a solicitação do cliente será guardada num ficheiro [request.txt] pelo procedimento 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 realizar um teste inicial, em que, no código HTML do documento, a tag 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). Solicitamos o URL http://localhost/form2/formulaire_get.aspx:

Image

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

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 um pedido HTTP GET para solicitar o URL [http://localhost/form2/formulaire_get.aspx]. Isto acontece sempre que o URL é fornecido pelo utilizador. Preenchemos o formulário da seguinte forma:

Image

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

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

Quando se clica no botão [Submit], o navegador envia os parâmetros do formulário (a tag <form>) para o URL especificado no atributo [action] da tag <form action="URL">, caso exista. Se este atributo não existir, os parâmetros do formulário são enviados para o URL que serviu o formulário. É este o caso aqui. O botão [Submit] deve, portanto, desencadear um pedido do navegador para o URL [http://localhost/form2/formulaire_get.aspx] com os parâmetros do formulário incluídos. Uma vez que a página [formulaire_get.aspx] armazena o pedido recebido, devemos conseguir ver como o cliente enviou estes parâmetros. Vamos experimentar. Clicamos no botão [Submit]. Recebemos a seguinte resposta do navegador:

Image

Esta é a página inicial, mas pode ver que o URL mudou no campo [Endereço] do navegador. Passou a ser o seguinte:

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

Podemos ver que as escolhas feitas no formulário se refletem no URL. Vejamos o conteúdo do ficheiro [request.txt], que armazenou 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

Esta é uma solicitação HTTP bastante semelhante à enviada inicialmente pelo navegador quando solicitou o documento sem passar quaisquer parâmetros. Existem duas diferenças:

GET HTTP/1.1 URL
Os parâmetros do formulário foram anexados à URL do documento na forma ?param1=val1&param2=val2&...
Referer
O cliente utiliza este cabeçalho HTTP para indicar a URL do documento que estava a exibir quando efetuou a solicitação

Vamos analisar mais detalhadamente como os parâmetros foram passados na solicitação GET URL?param1=value1&param2=value2&... HTTP/1.1, onde os parâmetros são os nomes dos controlos do formulário web e os valores são os valores a eles associados. Abaixo encontra-se uma tabela de três colunas:

  • Coluna 1: mostra a definição de um controlo HTML do exemplo
  • Coluna 2: mostra como este controlo aparece num navegador
  • Coluna 3: mostra o valor enviado ao servidor pelo navegador para o controlo da Coluna 1, na forma que assume na solicitação GET do exemplo
Controlo HTML
Exibição de pré-validação
Valor(es) devolvido(s)
<input type="radio" value="yes" name="rdMarie" />Sim
<input type="radio" checked
value="no" name="rdMarie" />Não
- o valor do atributo value do botão
selecionado pelo utilizador.
<input type="checkbox"
value="one" name="C1" />1
<input type="checkbox"
checked value="two" name="C2" />2
<input type="checkbox"
value="três" name="C3" />3
C1=um
C2=dois
- valores dos atributos value das caixas de seleção
marcadas pelo utilizador
<input type="text" maxlength="30" value="algumas
palavras" name="txtInput" />
txtSaisie=programação+asp.net
- texto digitado pelo utilizador no
. Os espaços foram substituídos
pelo sinal +
<input type="password"
maxlength="12" size="12"
value="aPassword"
name="txtMdp" />
txtMdp="thisIsSecret"
- texto digitado pelo utilizador no
. O texto realmente digitado foi
"thisIsSecret". O último caractere foi
perdido porque o
maxlength="12" limitou o número de
caracteres a 12.
<textarea name="areaSaisie">
linha1
linha2</textarea>
areaSaisie=os+conceitos+básicos+de+
a%0D%0A
programação+web
- texto digitado pelo utilizador na
. %OD%OA é o
. Os espaços foram
substituídos pelo sinal +
<select name="cmbValeurs">
<option value="1">opção1
</option>
<option value="2" selected>opção2
</option>
<option value="3">opção3
</option>
</select>
cmbValues=3
- valor selecionado pelo utilizador a partir da
lista de seleção única
<select size="3"
name="lstSimple">
<option value="1"
selected>list1</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 selecionado pelo utilizador a partir da
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>múltiplo3
</option>
<option value="4">múltiplo4
</option>
<option value="5">múltiplo5
</option>
</select>
lstMultiple=2
lstMultiple=4
- valores selecionados pelo utilizador na
lista de seleção múltipla
<input type="submit"
value="Enviar"
name="btnSubmit" />
btnEnvoyer=Submit
- atributos name e value do botão utilizado
foram utilizados para enviar os dados do formulário
para o servidor
<input type="hidden"
name="secret"
value="aValue" />
 
secret=aValue
- atributo value do campo oculto

Pode estar a perguntar-se o que o servidor fez com os parâmetros que lhe foram passados. Na verdade, nada. Ao receber o pedido

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 passou os parâmetros para a URL no documento [http://localhost/form2/formulaire_get.aspx], ou seja, para 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 isso que, em resposta ao nosso botão [Submit], recebemos a mesma página que a obtida inicialmente ao solicitar a 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 para o servidor web. Para tal, copiamos o ficheiro [form_get.aspx] para [form_post.aspx] e modificamos apenas a tag <form> em [form_post.aspx]:


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

Não há necessidade de alterar o controlador [form_get.aspx.vb], por isso deixamo-lo como está. Solicitamos o novo documento através do URL [http://localhost/form2/formulaire_post.aspx], preenchemos o formulário tal como fizemos para o método GET e enviamos os parâmetros para o servidor utilizando o botão [Submit]. Recebemos a seguinte página de resposta do servidor:

Image

Assim, obtemos o mesmo resultado que com o método GET, ou seja, a página inicial. Note uma diferença: no campo [Endereço] do navegador, os parâmetros transmitidos não aparecem. Agora, vamos ver o pedido enviado pelo cliente e 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

Novos elementos aparecem na solicitação HTTP do cliente:

POST HTTP/1.1
A solicitação GET foi substituída por uma solicitação POST. Os parâmetros já não estão presentes na primeira linha da solicitação. Podemos ver que agora estão colocados após a solicitação HTTP, seguindo uma linha em branco. A sua codificação é idêntica à da solicitação GET.
Content-Length
número de caracteres «enviados», ou seja, o número de caracteres que o servidor web deve ler após receber os cabeçalhos HTTP para recuperar o documento enviado pelo cliente. O documento em questão aqui é 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 contendo 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 utilizando o método GET, o navegador exibiria o URL solicitado no seu campo de endereço na forma URL?param1=val1&param2=val2&.... Isto pode ser visto como uma vantagem ou uma desvantagem:

  • uma vantagem se quiser permitir que o utilizador guarde esta URL parametrizada nos seus favoritos
  • uma desvantagem se não quiser que o utilizador tenha acesso a determinadas informações do formulário, tais como campos ocultos

A partir de agora, utilizaremos o método POST quase exclusivamente nos nossos formulários.

5.4. Processamento dos valores do formulário no lado do servidor

5.4.1. Visão geral do exemplo

Agora que estabelecemos a ligação entre a tag HTML <form method="GET/POST" ...> e a forma como o navegador envia os valores do formulário, sabemos como os recuperar no lado do servidor. O capítulo anterior forneceu a resposta:

  • se o método da tag <form> for GET, os valores dos parâmetros serão recuperados da coleção [Request.QueryString]
  • Se o método da tag <form> for POST, os valores dos parâmetros "enviados" serão recuperados da coleção [Request.Form]. É necessário um esclarecimento aqui. A tag <form> pode especificar o URL de destino para a solicitação GET ou POST usando o atributo [action]. Este URL pode ser configurado independentemente de se tratar de uma solicitação GET ou POST, na forma action="url?param1=val1&param2=val2&..". Estes parâmetros são então adicionados aos que se encontram entre as tags <form> e </form>, que serão enviados para o servidor através de uma solicitação GET ou POST. Como fazem parte da URL de destino, serão recuperados da coleção [Request.QueryString], independentemente de a solicitação ser GET ou POST.

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

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

A [form_view] é enviada ao utilizador, que a preenche e a submete. Pode ter este aspeto imediatamente antes da submissão:

Image

O utilizador clica no botão [Submit] para enviar as suas entradas. Em troca, recebe a seguinte [validation_view]:

Image

5.4.2. O controlador da aplicação

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

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

Consiste numa ú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)
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        Select Case action
            Case "init"
                Server.Transfer("formulaire.aspx", False)
            Case "validation"
                Server.Transfer("validation.aspx", True)
            Case Else
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub
End Class

O controlador funciona da seguinte forma:

  • procura uma cadeia de parâmetros que contenha o parâmetro [action] no URL de destino. Se este estiver em falta, comporta-se como se [action=init] estivesse presente na cadeia de parâmetros.
  • Apenas duas ações são reconhecidas:
    • init: o formulário pré-preenchido é enviado ao cliente
    • validation: a página que confirma as entradas do utilizador é enviada para o cliente
  • Se a ação não for uma das acima referidas, o sistema comporta-se como se [action=init] estivesse presente. Também pode ser devolvida 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 esta 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>

Vemos o código HTML do formulário que analisámos anteriormente, com algumas diferenças. O código da tag <form> foi modificado:


        <form name="formulaire" method="post" action="?action=validation">
  • post: os valores introduzidos pelo utilizador e enviados para o servidor quando o botão [submit] é clicado serão enviados utilizando o método HTTP POST
  • action: a sintaxe action="url" é utilizada para especificar o URL para o qual os valores do formulário devem ser enviados. Este URL pode incluir uma sequência de parâmetros na forma param1=val1&param2=val2&... É isso que é feito aqui, onde passamos o parâmetro [action=validation] para indicar ao controlador a ação que deve realizar. Note que esta cadeia de parâmetros não é precedida por um endereço web. O navegador enviará, portanto, os parâmetros do formulário para o endereço que forneceu este formulário. No nosso exemplo acima, este endereço é [http://localhost/mvcform1]. O navegador fará, assim, um pedido [POST /mvcform1?action=validation] para a máquina [localhost].

Foram adicionados botões para permitir ao utilizador desmarcar itens 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>

Ao clicar no botão [Limpar], todos os itens da lista a que está associado são desmarcados. Tomemos o exemplo da lista [lstMultiple]. Ao clicar no botão [Limpar] correspondente, é acionada a execução da função JavaScript [raz(lstMultiple)]. Lembre-se de que o código JavaScript num documento HTML apresentado por um navegador é executado pelo próprio navegador, e não pelo servidor. O JavaScript é uma linguagem muito abrangente que permite adicionar funcionalidades dinâmicas à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 representando uma lista HTML. Este objeto possui propriedades e métodos. Uma de suas propriedades é [selectedIndex], cujo valor é o número da primeira opção selecionada na lista HTML. Se não houver nenhuma, esta propriedade é -1. Por outro lado, definir um valor para esta propriedade seleciona um novo item na lista HTML, e defini-lo como -1 significa que nenhum item está selecionado. É isso que é feito aqui.

Por fim, note que o código de apresentação [form.aspx] não é acompanhado por um controlador [form.aspx.vb]. Na verdade, não há conteúdo dinâmico gerado pelo servidor no documento HTML, pelo que não há necessidade de um controlador.

5.4.4. Tratamento 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 esta tarefa. Visualmente, a página tem o seguinte aspeto:

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 <%=variable%> do documento são calculadas pelo controlador associado [validation.aspx.vb]:


Imports System.Text.RegularExpressions
 
Public Class validation
    Inherits System.Web.UI.Page
 
    Protected rdMarie As String
    Protected C1 As String
    Protected C2 As String
    Protected C3 As String
    Protected txtSaisie As String
    Protected txtMdp As String
    Protected areaSaisie As String
    Protected cmbValeurs As String
    Protected lstSimple As String
    Protected lstMultiple As String
    Protected secret As String
    Protected delimiteur As New Regex("\r\n")
 
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'retrieve posted parameters
        rdMarie = getValue("rdMarie")
        C1 = getValue("C1")
        C2 = getValue("C2")
        C3 = getValue("C3")
        txtSaisie = getValue("txtSaisie")
        txtMdp = getValue("txtMdp")
        areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
        cmbValeurs = getValue("cmbValeurs")
        lstSimple = getValue("lstSimple")
        lstMultiple = getValue("lstMultiple")
        secret = getValue("secret")
    End Sub
 
    Private Function getValue(ByVal champ As String) As String
        ' retrieves the value of field [field] from the posted request
        ' anything?
        If Request.Form(champ) Is Nothing Then Return ""
        ' retrieve the value(s) of the
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function
 
End Class

O cálculo dos valores a serem exibidos é realizado no procedimento [Form_Load]. O valor de um campo "preenchido" é obtido utilizando a 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 caracteres do parâmetro enviado, então a cadeia de caracteres vazia é devolvida como o valor de C
  • caso contrário, a matriz de valores para o campo C é obtida através de [Request.Form.GetValues(C)]. Estes são concatenados numa cadeia de caracteres na forma [val1][val2]...[valn], onde [vali] é o i-ésimo valor do campo C

O campo [areaSaisie] é tratado de forma especial. O seu valor é enviado pelo navegador na forma areaSaisie=line1\r\nline2\r\n... onde \r é o código ASCII 13 (retorno de carro) e \n é o código ASCII 10 (avanço de linha). A função getValue(areaSaisie) é, portanto, a cadeia de caracteres "line1\r\nline2\r\n...". Esta cadeia é dividida em linhas utilizando o método [Regex.Split]. Isto resulta numa matriz de cadeias de caracteres {line1,line2,...}. Esta matriz é convertida na cadeia de caracteres "line1,line2,..." utilizando o método [String.Join]. É esta cadeia de caracteres final que será apresentada como o valor do campo [areaSaisie]. O objetivo aqui era demonstrar como extrair as linhas individuais de um campo [TextArea] HTML.

5.4.5. Testes

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

Suponha que o formulário validado seja o seguinte:

Image

Ao clicar no botão [Submit], é apresentada a seguinte página:

Image

Primeiro, repare no URL de resposta: [http://localhost/mvcform1/?action=validation]. Este é o URL do atributo [action] da tag <form> no formulário [formulaire.aspx]:


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

Vamos examinar os valores obtidos para os diferentes campos do formulário, um por um:

campo
valor
HTML
comentários
rdMarie
sim
<input type="radio" value="sim"
name="rdMarie">Sim
<input type="radio" checked
value="no" name="rdMarie">Não
O valor obtido é o atributo [value] da caixa de seleção
C1
a
<input type="checkbox"
value="one" name="C1">1
o mesmo
C2
dois
<input type="checkbox"
marcado value="dois" name="C2">2
o mesmo
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] era, portanto, verdadeira.
txtInput
Programação
ASP.NET
<input type="text"
... name="txtSaisie">
O valor devolvido é o texto presente no campo de entrada no momento da validação
txtMdp
password
<input type="password"
...name="txtMdp">
same
campo de entrada
noções básicas de
programação web
<textarea name="areaSaisie">
...</textarea>
o mesmo
cmbValues
3
<select name="cmbValues">
...
<option value="3">opção3</option>
</select>
O valor obtido é o atributo [value] da opção selecionada
lstSimple
3
<select size="3" name="lstSimple">
....
<option value="3">list3</option>
...
</select>
igual
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
aValue
<input type="hidden"
name="secret" value="aValue">
O valor obtido é o atributo [value] do campo oculto

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

Image

  • a opção [choice1] está selecionada na caixa combinada
  • nenhuma opção está selecionada nas outras duas listas. Utilizámos os botões [Clear] para conseguir isto.

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

Image

Quando nenhum valor é selecionado numa lista, o navegador não envia um parâmetro para ela. 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 mostrado 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 para uma nova pasta. Adicionamos um link à página [validation.aspx] que permite ao utilizador regressar ao formulário:

Image

A alteração a ser feita na página [validation.aspx] é a 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 com um único parâmetro [action=form], permitindo que o servidor saiba que deve apresentar o formulário tal como estava quando foi enviado. Isto difere da ação [init], que apresenta um formulário predefinido. A URL com o parâmetro [?action=form] não tem, na verdade, uma URL. Será, portanto, a mesma que exibiu a página de envio. Como vimos no exemplo anterior, esta é a URL da pasta da aplicação. O pedido passará, portanto, pelo controlador. O controlador deve agora tratar da ação [form]. O código em [global.asax.vb] é modificado da seguinte forma:


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        Select Case action
            Case "init"
                Server.Transfer("formulaire.aspx", False)
            Case "validation"
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                Server.Transfer("formulaire.aspx", True)
            Case Else
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub

Se a ação for "form", simplesmente reencaminhamos o pedido para a página [form.aspx]. Sabemos que esta página apresenta um formulário predefinido sem partes variáveis. Por conseguinte, esta página não pode apresentar o formulário com os valores que tinha quando foi enviado. Estamos a tentar destacar este ponto aqui. 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, solicitamos o URL [http://localhost/mvcform2]. Obtemos a seguinte página (visualização parcial):

Image

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

Image

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

Image

Utilizamos o link [Voltar ao formulário] presente (mas não visível) na página acima. Recebemos a seguinte resposta do servidor:

Image

Observamos que:

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

Sabemos por que não conseguimos recuperar os valores introduzidos. Se analisarmos o código do documento [form.aspx], vemos que tudo é estático, pelo que é obrigado a apresentar a mesma página sempre. É evidente que precisamos de tornar este código dinâmico. Tem de apresentar os valores validados pelo utilizador. Mas onde os devemos armazenar?

Recordemos a lei de ferro do protocolo HTTP sem estado:

  • O URL [http://localhost/mvcform2] é solicitado — uma resposta é recebida. Uma ligação TCP-IP foi aberta entre o cliente e o servidor no início do pedido e fechada no final da resposta.
  • O utilizador introduz e, em seguida, envia os dados. A URL [http://localhost/mvcform2/?action=validation] é solicitada — uma resposta é recebida. Uma nova ligação TCP/IP foi aberta e depois encerrada entre as duas partes.
  • O utilizador clica na ligação [Voltar ao formulário]. A URL [http://localhost/mvcform2/?action=formulaire] é solicitada — é recebida uma resposta. Foi aberta e, em seguida, encerrada uma nova ligação TCP/IP entre as duas partes.

Os ciclos de solicitação-resposta são independentes uns dos outros porque cada um utiliza uma nova ligação TCP-IP. Quando uma aplicação cliente-servidor utiliza uma única ligação TCP-IP para uma série de trocas, o servidor pode identificar um cliente através da sua ligação. Pode, portanto, armazenar informações que irá associar a uma ligação específica e, assim, acompanhar as trocas. Quando as trocas ocorrem através de ligações diferentes, o servidor não consegue identificar um cliente por meio de uma ligação. É necessário outro método. Apresentámos um desses métodos 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 subsequentes.

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

  • Quando o utilizador enviar os seus dados (action=validation), o controlador [main.aspx.vb] irá armazená-los na sessão atual antes de apresentar a página de validação.
  • Quando o formulário precisar de ser apresentado com os valores introduzidos (action=form), 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 da aplicação

O controlador da aplicação é composto por 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
        ' retrieve the action to be performed
        Dim action As String
        If Request.QueryString("action") Is Nothing Then
            action = "init"
        Else
            action = Request.QueryString("action").ToString.ToLower
        End If
        ' execute the action
        Select Case action
            Case "init"
                ' the pre-filled form is displayed
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
            Case "validation"
                ' the confirmation page is displayed after saving the values posted in the session
                Session.Item("formulaire") = Request.Form
                Server.Transfer("validation.aspx", True)
            Case "formulaire"
                ' displays the form with values taken from the session
                Context.Items("formulaire") = Session.Item("formulaire")
                Server.Transfer("formulaire.aspx", True)
            Case Else
                ' the pre-filled form is displayed
                Context.Items("formulaire") = initForm()
                Server.Transfer("formulaire.aspx", True)
        End Select
    End Sub
 
    Private Function initForm() As NameValueCollection
        ' initialize the form
        Dim form As New NameValueCollection
        form.Set("rdMarie", "non")
        form.Set("C2", "deux")
        form.Set("txtSaisie", "qqs mots")
        form.Set("txtMdp", "ceciestsecret")
        form.Set("areasaisie", "ligne1" + ControlChars.CrLf + "ligne2" + ControlChars.CrLf)
        form.Set("cmbValeurs", "2")
        form.Set("lstSimple", "1")
        form.Set("lstMultiple", "1")
        form.Add("lstMultiple", "3")
        Return form
    End Function
End Class

Vemos a essência da estrutura do controlador de aplicações discutida anteriormente, com as seguintes diferenças:

  • o trabalho do controlador é executado 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 "form". A execução é então transferida para a página [validation.aspx], que irá apresentar esses valores.
  • Para outras ações, a execução é transferida em todos os casos para a página [formulaire.aspx]. Esta página espera uma chave "formulaire" no seu contexto, que será associada a um objeto do tipo [Request.Form], ou seja, do tipo [NameValueCollection]. Este objeto deve conter a coleção de valores para os campos do formulário.
  • Se a ação for [init] ou uma ação não reconhecida, a coleção de valores é construída arbitrariamente pela função [initForm].
  • Se a ação for [form], esta coleção é a coleção [Request.Form] que foi 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 [form.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 [yes] for selecionado; caso contrário, o valor ""
rdnonchecked
o mesmo para o botão de opção [no]
c1checked
o mesmo para a caixa de seleção [C1]
c2checked
o mesmo para a caixa de seleção [C2]
c3checked
o mesmo para a caixa de seleção [C3]
txtInput
o texto a inserir no campo [txtInput]
txtPassword
o texto a inserir no campo [txtPassword]
inputArea
o texto a inserir no campo [areaInput]
cmbOptionValues
o texto HTML para as opções na lista suspensa [cmbValeurs]
lstSimpleOptions
o texto HTML das opções na lista suspensa [lstSimple]
lstMultipleOptions
o texto HTML das opções na lista suspensa [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
 
    ' constant form fields
    Private libellésCmbValeurs() As String = {"choix1", "choix2", "choix3"}
    Private valeursCmbValeurs() As String = {"1", "2", "3"}
    Private libellésLstSimple() As String = {"liste1", "liste2", "liste3"}
    Private valeursLstSimple() As String = {"1", "2", "3"}
    Private libellésLstMultiple() As String = {"multiple1", "multiple2", "multiple3", "multiple4", "multiple5"}
    Private valeursLstMultiple() As String = {"1", "2", "3", "4", "5"}
 
    ' dynamic form fields
    Protected rdouichecked As String
    Protected rdnonchecked As String
    Protected c1checked As String
    Protected c2checked As String
    Protected c3checked As String
    Protected txtSaisie As String
    Protected txtMdp As String
    Protected areaSaisie As String
    Protected cmbValeursOptions As String
    Protected lstSimpleOptions As String
    Protected lstMultipleOptions As String
 
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' retrieve the previous request from the session
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If
        ' prepare the page to be displayed
        ' radio buttons
        rdouichecked = ""
        rdnonchecked = "checked"
        If isEqual(form("rdMarie"), "oui") Then
            rdouichecked = "checked"
            rdnonchecked = ""
        End If
        ' checkboxes
        c1checked = ""
        If isEqual(form("C1"), "un") Then c1checked = "checked"
        c2checked = ""
        If isEqual(form("C2"), "deux") Then c2checked = "checked"
        c3checked = ""
        If isEqual(form("C3"), "trois") Then c3checked = "checked"
        ' input fields
        txtSaisie = ""
        If Not form("txtSaisie") Is Nothing Then txtSaisie = form("txtSaisie").ToString
        txtMdp = ""
        If Not form("txtMdp") Is Nothing Then txtMdp = form("txtMdp").ToString
        areaSaisie = ""
        If Not form("areaSaisie") Is Nothing Then areaSaisie = form("areaSaisie").ToString
        ' lists
        Dim sélections() As String = {}
        If Not form("cmbValeurs") Is Nothing Then sélections = form.GetValues("cmbValeurs")
        cmbValeursOptions = getOptions(valeursCmbValeurs, libellésCmbValeurs, sélections)
        sélections = New String() {}
        If Not form("lstSimple") Is Nothing Then sélections = form.GetValues("lstSimple")
        lstSimpleOptions = getOptions(valeursLstSimple, libellésLstSimple, sélections)
        sélections = New String() {}
        If Not form("lstMultiple") Is Nothing Then sélections = form.GetValues("lstMultiple")
        lstMultipleOptions = getOptions(valeursLstMultiple, libellésLstMultiple, sélections)
    End Sub
 
    Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
        ' renders HTML code for <select> tag options
        ' values: table of tag option values
        ' labels: table of tag option labels
        ' selections: options to select
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' browse the list of option values
        For iValeur = 0 To valeurs.Length - 1
            ' check whether the current value should be selected
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' we integrate the HTML code from the
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' we return the result
        Return toString
    End Function
 
    Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
        ' returns true if field is equal to value
        If champ Is Nothing OrElse champ.ToString <> valeur Then
            Return false
        Else
            Return true
        End If
    end function
End Class

Quando a página [form.aspx] começar a ser executada, encontrará no seu contexto uma chave "form" associada à coleção de valores de campo que precisa de apresentar.


        ' retrieve the previous request from the session
        Dim form As NameValueCollection
        If Not Context.Items("formulaire") Is Nothing Then
            form = Context.Items("formulaire")
        Else
            form = New NameValueCollection
        End If

Poder-se-á perguntar por que razão verificamos se [Context.Items("form")] existe. Na verdade, o controlador atribui um valor a este objeto em todos os casos. No entanto, nada impede que o cliente solicite diretamente a página [form.aspx] sem passar pelo controlador. Se fosse esse o caso, o código anterior funcionaria com uma coleção vazia de valores, mas não haveria qualquer «falha».

O código percorre a coleção de valores que recebeu para calcular todas as variáveis dinâmicas da página HTML associada. Embora seja extenso, este código não é particularmente complicado, e deixaremos que o leitor o explore para não sobrecarregar esta explicação. No entanto, iremos concentrar-nos em como gerar o código HTML para as três listas [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
        ' renders HTML code for <select> tag options
        ' values: table of tag option values
        ' labels: table of tag option labels
        ' selections: options to select
        Dim iValeur As Integer
        Dim iSelection As Integer
        Dim selected As String
        Dim toString As String = ""
        ' browse the list of option values
        For iValeur = 0 To valeurs.Length - 1
            ' check whether the current value should be selected
            selected = "" : iSelection = 0
            Do While iSelection < sélections.Length And selected = ""
                If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
                iSelection += 1
            Loop
            ' we integrate the HTML code of the
            toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
            + libelles(iValeur) + "</option>" + ControlChars.CrLf
        Next
        ' we return the result
        Return toString
    End Function

Note que as opções de uma tag <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] se a opção deve ser selecionada na lista

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

  1. a matriz de valores das opções em [values]
  2. a matriz de textos das opções em [labels]
  3. a matriz de valores a selecionar em [selections]

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
        'retrieve posted parameters
        rdMarie = getValue("rdMarie")
        C1 = getValue("C1")
        C2 = getValue("C2")
        C3 = getValue("C3")
        txtSaisie = getValue("txtSaisie")
        txtMdp = getValue("txtMdp")
        areaSaisie = String.Join(",", delimiteur.Split(getValue("areaSaisie")))
        cmbValeurs = getValue("cmbValeurs")
        lstSimple = getValue("lstSimple")
        lstMultiple = getValue("lstMultiple")
        secret = getValue("secret")
        ' save them in the session
        'Session("formulaire") = Request.Form
    End Sub
 
    Private Function getValue(ByVal champ As String) As String
        ' retrieves the value of field [field] from the posted request
        ' anything?
        If Request.Form(champ) Is Nothing Then Return ""
        ' retrieve the value(s) of the
        Dim valeurs() As String = Request.Form.GetValues(champ)
        Dim valeur As String = ""
        Dim i As Integer
        For i = 0 To valeurs.Length - 1
            valeur += "[" + valeurs(i) + "]"
        Next
        Return valeur
    End Function
End Class

5.5.5. Testes

Os ficheiros [main.aspx, main.aspx.vb, form.aspx, form.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, solicitamos o URL [http://localhost/mvcform3/main.aspx]. Obtemos o formulário pré-inicializado:

Image

Preenchemos o formulário da seguinte forma:

Image

Clicamos no botão [Submit] acima. Recebemos a seguinte resposta do servidor:

Image

Utilizamos o link [Voltar ao formulário] acima para regressar ao formulário. Recebemos a seguinte nova resposta:

Image

Vemos o formulário exatamente como o enviá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 não é uma tarefa trivial. Veremos num capítulo posterior que, com o ASP.NET, é possível deixar que o servidor restaure o estado de uma página por si próprio.