5. Gestión de la interfaz de usuario
5.1. Introduction
En la relación cliente-servidor de la web, el cliente transmite información al servidor en forma de cadena de parámetros [param1=val1¶m2=val2&...]. En nuestros ejemplos anteriores, hemos construido esta cadena, en la mayoría de los casos, manualmente, solicitando URL del tipo [http://localhost/appli? param1=val1¶m2=val2&...]. En la práctica, la información que el cliente transmite al servidor procede de formularios que el usuario ha rellenado. En este capítulo exploramos cómo se construyen dichos formularios. También presentamos la herramienta WebMatrix, que nos permitirá diseñar las interfaces de usuario. La instalación de esta herramienta se describe en los anexos.
5.2. El lenguaje HTML
5.2.1. Un ejemplo
Consideremos el siguiente ejemplo, creado con [Web Matrix], que presenta:
- una tabla
- una imagen
- un enlace

Ejecutemos [WebMatrix] y, a continuación, seleccionemos la opción [File/New File]:

Decidimos crear una página HTML. La información anterior creará un archivo [d:\data\devel\aspnet\chap4\exemple1\exemple1.htm]. [WebMatrix] ofrece dos opciones para editar este archivo: el modo [Design] y el modo [HTML]:

El modo [Design] permite utilizar la paleta de componentes HTML que ofrece [WebMatrix]:

Para insertar un elemento de esta paleta, basta con hacer doble clic sobre él y, a continuación, colocarlo en la ventana [Design]. El modo [HTML] permite crear el documento HTML mediante un editor de texto. Para ello, es necesario conocer la sintaxis del lenguaje HTML. En la pestaña [HTML] se ha generado un esqueleto de documento:

La ventana [HTML] resulta muy útil para quienes no conocen el lenguaje HTML. El usuario crea su documento en la ventana [Design] y comprueba el código HTML generado en la ventana [HTML]. De este modo, va adquiriendo poco a poco el dominio de HTML y, en poco tiempo, puede trabajar únicamente con el editor de texto sin necesidad del modo [Design]. Ahora vamos a mostrar cómo crear el documento HTML presentado al principio de esta sección. Trabajamos en la ventana [Design]. En primer lugar, introducimos directamente la primera línea de texto:

- Añadimos el componente [Horizontal Rule] en la paleta de componentes:

- añadimos el componente [Table]:

- Colocamos el cursor en la tercera fila de la tabla para eliminarla con la opción [HTML/Edit Table/Delete Table Row]. A continuación, introducimos el texto deseado en cada celda:

- colocamos el cursor en una de las celdas de la tabla y consultamos sus propiedades. La ventana de propiedades aparece en la parte inferior derecha del entorno de trabajo:

- La celda está representada por la etiqueta HTML <TD>. Por lo tanto, se nos muestran las propiedades de la etiqueta <TD>. Nos centramos en la tabla, que es un objeto que engloba a la celda. Hacemos clic en la lista desplegable (click to see parent HTML elements) situada arriba para seleccionar el objeto <TABLE>:

- El objeto <TABLE> tiene una propiedad [border] que establece el ancho del borde que rodea las celdas de la tabla. En este caso, tomamos border=1.

- Ahora editamos los atributos del objeto <TD> de la celda (1,2) para establecer align=Center y width=200 (píxeles). El texto quedará centrado en la celda (align=center) y esta tendrá una anchura de 200 píxeles. Para ver el cambio, a veces puede que tengas que seleccionar la pestaña [HTML] y luego volver a la pestaña [Design]:

- Ahora colocamos el texto que precede a la imagen:

- y, a continuación, la imagen haciendo doble clic en el componente [image] de la paleta:

- Seleccionamos la imagen para editar sus propiedades:

- En el atributo [src], introducimos el nombre del archivo que contiene la imagen, en este caso [univ01.gif]:

- Introducimos el texto que precede al enlace:

- convertimos el texto «[ici]» en un enlace a la URL «[http://istia.univ-angers.fr]». Para ello, lo seleccionamos y elegimos la opción «[HTML/Insert Hyperlink]»:

- obtenemos el siguiente resultado:

- Ya casi lo tenemos. Veamos el código HTML generado en la pestaña [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>
Nos quedan algunos detalles por resolver. En primer lugar, nos gustaría ponerle un título a nuestro documento. [WebMatrix] no permite hacerlo en el modo [Design]. En la pestaña [HTML] sustituimos la secuencia <head>..</head> por la siguiente secuencia:
Por otra parte, nos gustaría que el texto [Le langage HTML - 1] apareciera en letra más grande. La secuencia <Hi>texto</Hi> permite establecer el tamaño de un texto, donde i varía de 1 a 6, de mayor a menor. En este caso, utilizaremos H2. La secuencia
se convierte en:
La ventana [Design] refleja nuestros cambios:

Ahora solo nos queda probarlo con la opción [View/Start] o [F5]. [WebMatrix] solicita algunos datos para iniciar el servidor web [Cassini]:

Podemos aceptar los valores propuestos por defecto. Se inicia el servidor [Cassini] y nuestra página se muestra en un navegador:

Por curiosidad, podemos comprobar con qué parámetros se ha iniciado [Cassini]:

Hemos presentado los fundamentos para crear una página HTML con [WebMatrix]. Se invita al lector a crear otras páginas HTML y a comprobar cada vez el código HTML generado. Poco a poco, será capaz de crear una página sin necesidad de recurrir al modo [Design]. Un documento HTML tiene la siguiente estructura general:
Todo el documento está enmarcado por las etiquetas <html>...</html>. Se compone de dos partes:
<head>...</head>: es la parte no visible del documento. Proporciona información al navegador que va a mostrar el documento. A menudo contiene la etiqueta <title>...</title>, que establece el texto que se mostrará en la barra de título del navegador. También puede contener otras etiquetas, en particular aquellas que definen las palabras clave del documento, palabras clave que posteriormente utilizan los motores de búsqueda. En esta parte también pueden encontrarse scripts, escritos normalmente en JavaScript o VBScript, que serán ejecutados por el navegador.
<body atributos>...</body>: es la parte que mostrará el navegador. Las etiquetas HTML contenidas en esta parte indican al navegador el aspecto visual «deseado» para el documento. Cada navegador interpretará estas etiquetas a su manera. Por lo tanto, dos navegadores pueden mostrar de forma diferente un mismo documento web. Esto suele ser uno de los quebraderos de cabeza de los diseñadores web.
El código HTML del documento anterior era el siguiente:
<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 y ejemplos HTML |
<title>HTML1</title> HTML1 aparecerá en la barra de título del navegador que muestre el documento | |
<hr>: muestra una línea horizontal | |
<atributos de tabla>....</table>: para definir la tabla <tr atributos>...</tr>: para definir una fila <td atributos>...</td>: para definir una celda Ejemplos: <table border="1">...</table>: el atributo border define el grosor del borde de la tabla <td align="center" width="200">celda(1,2)</td>: define una celda cuyo contenido será cellule(1,2). Este contenido se centrará horizontalmente (align="center"). La celda tendrá una anchura de 200 píxeles (width="200") | |
<img src="univ01.gif" />: define una imagen cuyo archivo de origen es univ01.gif en el servidor web (src="univ01.gif"). Este enlace se encuentra en un documento web obtenido con el URL http://localhost/exemple1.htm. Por lo tanto, el navegador solicitará el archivo URL http://localhost/univ01.gif para obtener la imagen a la que se hace referencia aquí. | |
<a href="http://istia.univ-angers.fr">aquí</a>: hace que el texto ici sirva de enlace hacia URL http://istia.univ-angers.fr. |
En este sencillo ejemplo se puede ver que, para generar el documento completo, el navegador debe realizar dos solicitudes al servidor:
http://localhost/exemple1.htm para obtener el código fuente HTML del documento
http://localhost/univ01.gif para obtener la imagen univ01.gif
5.2.2. Creación de un formulario
Un formulario HTML tiene como objetivo presentar al usuario una página de introducción de datos similar a los formularios de Windows. El formulario se envía al navegador en forma de documento HTML. Este mostrará el formulario al usuario, quien lo rellenará y lo validará mediante un botón con esa función. A continuación, el navegador transmitirá los valores introducidos al servidor para su procesamiento. Veremos que no envía al servidor la totalidad del formulario, sino solo los valores introducidos. El siguiente ejemplo muestra un formulario web creado también con WebMatrix:

El código HTML generado por [WebMatrix] es el siguiente:
<html>
<head>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
</script>
</head>
<body>
<p>
Gestion d'un formulaire
</p>
<hr />
<form name="formulaire" method="post">
<table border="1">
<tr>
<td>
Etes-vous marié(e)</td>
<td>
<p align="center">
<input type="radio" value="oui" name="rdMarie" />Oui
<input type="radio" checked value="non" name="rdMarie" />Non
</p>
</td>
</tr>
<tr>
<td>
Cases à cocher
</td>
<td>
<p align="center">
<input type="checkbox" value="un" name="C1" />1
<input type="checkbox" checked value="deux" name="C2" />2
<input type="checkbox" value="trois" name="C3" />3
</p>
</td>
</tr>
<tr>
<td>
Champ de saisie</td>
<td>
<p align="center">
<input type="text" maxlength="30" value="qqs mots" name="txtSaisie" />
</p>
</td>
</tr>
<tr>
<td>
Mot de passe</td>
<td>
<p align="center">
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" />
</p>
</td>
</tr>
<tr>
<td>
Boîte de saisie</td>
<td>
<p align="center">
</p>
<textarea name="areaSaisie">ligne1
ligne2</textarea>
</td>
</tr>
<tr>
<td>
ComboBox</td>
<td>
<p align="center">
</p>
<select name="cmbValeurs">
<option value="1">choix1</option>
<option value="2" selected>choix2</option>
<option value="3">choix3</option>
</select>
</td>
</tr>
<tr>
<td>
Liste à choix simple</td>
<td>
<p align="center">
</p>
<select size="3" name="lstSimple">
<option value="1" selected>liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>
Liste à choix multiple</td>
<td>
<p align="center">
</p>
<select multiple size="3" name="lstMultiple">
<option value="1" selected>multiple1</option>
<option value="2">multiple2</option>
<option value="3" selected>multiple3</option>
<option value="4">multiple4</option>
<option value="5">multiple5</option>
</select>
</td>
</tr>
<tr>
<td>
Bouton simple</td>
<td>
<p align="center">
<input onclick="effacer()" type="button" value="Effacer" name="btnEffacer" />
</p>
</td>
</tr>
<tr>
<td>
Bouton submit</td>
<td>
<p align="center">
<input type="submit" value="Envoyer" name="btnEnvoyer" />
</p>
</td>
</tr>
<tr>
<td>
Bouton reset</td>
<td>
<p align="center">
<input type="reset" value="Rétablir" name="btnRetablir" runat="server" />
</p>
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur" />
</form>
</body>
</html>
La correspondencia entre el control visual y la etiqueta HTML es la siguiente:
Comprobación | etiqueta HTML |
<form name="formulario" method="post"> | |
<input type="text" maxlength="30" value="unas palabras" name="txtSaisie" /> | |
<input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> | |
<textarea name="areaSaisie">línea1 línea 2</textarea> | |
<input type="radio" value="sí" name="rdMarie" />Sí <input type="radio" checked value="no" name="rdMarie" />No | |
<input type="checkbox" value="uno" name="C1" />1 <input type="checkbox" checked value="dos" name="C2" />2 <input type="checkbox" value="tres" name="C3" />3 | |
<select name="cmbValeurs"> <option value="1">opción1</option> <option value="2" selected>opción 2</option> <option value="3">opción 3</option> </select> | |
<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> | |
<select multiple size="3" name="lstMultiple"> <option value="1" selected>múltiple1</option> <option value="2">múltiple2</option> <option value="3" selected>multiple3</option> <option value="4">multiple4</option> <option value="5">multiple5</option> </select> | |
<input type="hidden" name="secret" value="uneValeur" /> | |
<input type="submit" value="Enviar" name="btnEnvoyer" /> | |
<input type="reset" value="Restablecer" name="btnRetablir" runat="server" /> | |
<input onclick="effacer()" type="button" value="Borrar" name="btnEffacer" /> |
Repasemos estos diferentes controles.
5.2.2.1. El formulario
<form name="formulario" method="post"> |
<form name="..." method="..." action="...">...</form> | |
name="frmexemple": nombre del formulario method="..." : método utilizado por el navegador para enviar al servidor web los valores recopilados en el formulario action="..." : URL a la que se enviarán los valores recopilados en el formulario. Un formulario web está delimitado por las etiquetas <form>...</form>. El formulario puede tener un nombre (name="xx"). Esto se aplica a todos los controles que pueden encontrarse en un formulario. Este nombre resulta útil si el documento web contiene scripts que deben hacer referencia a elementos del formulario. El objetivo de un formulario es recopilar la información introducida por el usuario mediante el teclado o el ratón y enviarla a una URL del servidor web. ¿Cuál? La que se indica en el atributo action="URL". Si este atributo no está presente, la información se enviará al servidor del documento en el que se encuentra el formulario. ¿Cómo hace un cliente web para enviar información (la contenida en el formulario) a un servidor web? Ya lo hemos visto en detalle. Puede utilizar dos métodos diferentes denominados POST y GET. El atributo method="méthode", con el método igual a GET o POST, de la etiqueta <form> indica al navegador el método que debe utilizar para enviar la información recopilada en el formulario a la URL especificada por el atributo action="URL". Cuando no se especifica el atributo method, se utiliza por defecto el método GET. |
5.2.2.2. Campo de entrada

<input type="text" maxlength="30" value="unas palabras" name="txtSaisie" /> <input type="password" maxlength="12" size="12" value="unMotDePasse" name="txtMdp" /> |
<input type="..." name="..." size=".." value=".."> La etiqueta `input` existe para diversos controles. Es el atributo type el que permite diferenciar estos controles entre sí. | |
type="text": especifica que se trata de un campo de entrada type="password": los caracteres del campo de entrada se sustituyen por asteriscos (*). Esta es la única diferencia con respecto al campo de entrada normal. Este tipo de control es adecuado para introducir contraseñas. size="12": número de caracteres visibles en el campo; no impide introducir más caracteres maxlength="30": establece en 30 el número máximo de caracteres; el navegador se encarga de hacer cumplir este atributo name="txtSaisie": nombre del control value="unas palabras": texto que se mostrará en el campo de entrada. |
5.2.2.3. Campo de entrada multilínea

<textarea name="areaSaisie">línea1 línea 2</textarea> |
<textarea ...>texto</textarea> muestra un campo de entrada de varias líneas que contiene texto de forma predeterminada | |
rows="2": número de líneas cols="'20": número de columnas name="areaSaisie": nombre del control |
5.2.2.4. Botones de opción
![]()
<input type="radio" value="sí" name="rdMarie" />Sí <input type="radio" checked value="no" name="rdMarie" />No |
<input type="radio" atributo2="valor2" ..../>texto muestra un botón de opción con texto al lado. | |
name="rdMarie": nombre del control. Los botones de opción que tienen el mismo nombre forman un grupo de botones que se excluyen entre sí: solo se puede marcar uno de ellos. value="valor": valor asignado al botón de opción. No hay que confundir este valor con el texto que aparece junto al botón de opción, ya que este último solo tiene fines de visualización. checked: si se incluye esta palabra clave, el botón de opción aparece marcado; en caso contrario, no lo está. |
5.2.2.5. Casillas de selección
<input type="checkbox" value="uno" name="C1" />1 <input type="checkbox" checked value="dos" name="C2" />2 <input type="checkbox" value="tres" name="C3" />3 |
![]()
<input type="checkbox" atributo2="valor2" ..../>texto muestra una casilla de selección con texto al lado. | |
name="C1": nombre del control. Las casillas de selección pueden tener o no el mismo nombre. Las casillas que tienen el mismo nombre forman un grupo de casillas asociadas. value="valor": valor asignado a la casilla de selección. No hay que confundir este valor con el texto que aparece junto al botón de radio. Este último solo tiene fines de visualización. checked: si está presente esta palabra clave, el botón de radio está marcado; en caso contrario, no lo está. |
5.2.2.6. Lista desplegable (combo)
<select name="cmbValeurs"> <option value="1">opción1</option> <option value="2" selected>opción 2</option> <option value="3">opción 3</option> </select> |
![]()
<select size=".." name=".."> <option [selected="selected"] [value="valeur"]>texto</option> ... </select> muestra en una lista los textos comprendidos entre las etiquetas <option>...</option> | |
name="cmbValeurs": nombre del control. size="1": número de elementos visibles de la lista. size="1" convierte la lista en el equivalente a un cuadro combinado. Es el valor por defecto si no se incluye el atributo [size]. selected="selected": si este atributo está presente en un elemento de la lista, dicho elemento aparece seleccionado en la lista. En nuestro ejemplo anterior, el elemento de la lista choix2 aparece como el elemento seleccionado del cuadro combinado cuando este se muestra por primera vez. value="valor": establece el valor que se enviará al servidor si se selecciona el elemento. Si este atributo no está presente, se envía al servidor el texto asociado a la opción. |
5.2.2.7. Lista de selección ú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> |

<select size=".." name=".."> <option [selected] [value="valeur"]>...</option> ... </select> muestra en una lista los textos comprendidos entre las etiquetas <option>...</option> | |
los mismos que para la lista desplegable que solo muestra un elemento. Este control solo se diferencia de la lista desplegable anterior en su atributo size>1. |
5.2.2.8. Lista de selección múltiple
<select multiple size="3" name="lstMultiple"> <option value="1" selected>multiple1</option> <option value="2">multiple2</option> <option value="3" selected>multiple3</option> <option value="4">multiple4</option> <option value="5">multiple5</option> </select> |

<select size=".." name=".." multiple> <option [selected] ] [value="valeur"]>...</option> ... </select> muestra en una lista los textos comprendidos entre las etiquetas <option>...</option> | |
múltiple: permite seleccionar varios elementos de la lista. En el ejemplo anterior, se seleccionan los elementos liste1 y liste3. |
5.2.2.9. Botón de tipo «button»
<input onclick="effacer()" type="button" value="Borrar" name="btnEffacer" /> |
![]()
<input type="button" value="..." name="..." onclick="effacer()" ....> | |
type="button": define un control de botón. Existen otros dos tipos de botón: los tipos submit y reset. value="Borrar": el texto que se muestra en el botón onclick="función()": permite definir una función que se ejecutará cuando el usuario haga clic en el botón. Esta función forma parte de los scripts definidos en el documento web mostrado. La sintaxis anterior es una sintaxis javascript. Si los scripts están escritos en VBScript, habría que escribir onclick="función" sin los paréntesis. La sintaxis es idéntica si hay que pasar parámetros a la función: onclick="función(val1, val2,...)" En nuestro ejemplo, al hacer clic en el botón Effacer se invoca la siguiente función JavaScript effacer: La función effacer muestra un mensaje: ![]() |
5.2.2.10. Botón de tipo «submit»
<input type="submit" value="Enviar" name="btnEnvoyer" /> |
![]()
<input type="submit" value="Enviar" name="btnEnvoyer"> | |
type="submit": define el botón como un botón para enviar los datos del formulario al servidor web. Cuando el usuario haga clic en este botón, el navegador enviará los datos del formulario a la URL URL definida en el atributo action de la etiqueta <form>, según el método definido por el atributo method de dicha etiqueta. value="Enviar": el texto que se muestra en el botón |
5.2.2.11. Botón de tipo «reset»
<input type="reset" value="Restablecer" name="btnRetablir" runat="server" /> |
![]()
<input type="reset" value="Restablecer" name=" btnRetablir "> | |
type="reset": define el botón como un botón de restablecimiento del formulario. Cuando el usuario haga clic en este botón, el navegador restablecerá el formulario al estado en el que lo recibió. value="Restablecer": el texto que se muestra en el botón |
5.2.2.12. Campo oculto
<input type="hidden" name="secret" value="uneValeur" /> |
<input type="hidden" name="..." value="..."> | |
type="hidden": indica que se trata de un campo oculto. Un campo oculto forma parte del formulario, pero no se muestra al usuario. Sin embargo, si este solicitara a su navegador que mostrara el código fuente, vería la presencia de la etiqueta <input type="hidden" value="..."> y, por lo tanto, el valor del campo oculto. value="unValor": valor del campo oculto. ¿Para qué sirve el campo oculto? Permite al servidor web conservar información a lo largo de las solicitudes de un cliente. Pensemos en una aplicación de compras en línea. El cliente compra un primer artículo art1 en una cantidad de q1 en una primera página de un catálogo y, a continuación, pasa a otra página del catálogo. Para recordar que el cliente ha comprado q1 artículos art1, el servidor puede introducir estos dos datos en un campo oculto del formulario web de la nueva página. En esta nueva página, el cliente compra los artículos q2 y art2. Cuando los datos de este segundo formulario se envíen al servidor (submit), este no solo recibirá la información (q2, art2), sino también (q1, art1), que también forma parte del formulario como campo oculto no modificable por el usuario. A continuación, el servidor web introducirá en un nuevo campo oculto la información (q1,art1) y (q2,art2) y enviará una nueva página del catálogo. Y así sucesivamente. |
5.3. Envío de los valores de un formulario a un servidor web mediante un navegador
Ya sabemos, gracias al capítulo anterior, cómo un cliente envía información al servidor. Lo hace mediante:
- una solicitud HTTP GET url?param1=va1¶m2=val2&....
- una solicitud HTT POST url seguida de un documento que contiene la cadena de parámetros param1=va1¶m2=val2&....
El navegador utilizará uno de estos dos métodos dependiendo de si el atributo [method] de la etiqueta [form] es GET o POST. Esto es lo que vamos a mostrar ahora. La página analizada anteriormente es una página estática. Para poder acceder a los encabezados HTTP enviados por el navegador que va a solicitar este documento, la transformamos en una página dinámica para un servidor web .NET (IIS o Cassini). El código estático anterior se coloca en un archivo [formulaire_get.aspx] y su contenido es el siguiente:
<%@ Page src="formulaire_get.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="formulaire_get" %>
<html>
<head>
<title>Formulaire</title>
<script language="javascript">
function effacer(){
alert("Vous avez cliqué sur le bouton [Effacer]");
}
</script>
</head>
<body>
.....
</body>
</html>
La página de presentación anterior está asociada al 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 la consulta actual en request.txt de la carpeta de la página
Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"
Me.Request.SaveAs(requestFileName, True)
End Sub
End Class
Cada vez que se llame al documento [formulaire_get.aspx], la solicitud del cliente se guardará en un archivo [request.txt] mediante el procedimiento Page_Init. Ya nos hemos encontrado con este modo de funcionamiento, por lo que no haremos más comentarios sobre el controlador.
5.3.1. Método GET
Hagamos una primera prueba, en la que, en el código HTML del documento, la etiqueta FORM se define de la siguiente manera:
<form name="formulaire" method="get">
Colocamos los archivos [formulaire_get.aspx] y [formulaire_get.aspx.vb] en una carpeta <application-path> e iniciamos el servidor Cassini con los parámetros (<application-path>,/form2). Accedemos a la URL http://localhost/form2/formulaire_get.aspx:

El navegador acaba de realizar una solicitud y sabemos que esta se ha guardado en el archivo [request.txt]. Veamos su contenido:
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
El navegador ha utilizado una solicitud HTTP GET para solicitar la URL [http://localhost/form2/formulaire_get.aspx]. Esto ocurre siempre que el usuario introduce la URL. Rellenamos el formulario de la siguiente manera:

Utilizamos el botón [Envoyer] que aparece arriba. Su código HTML es el siguiente:
Al pulsar un botón del tipo [Submit], el navegador envía los parámetros del formulario (etiqueta <form>) al URL indicado en el atributo [action] de la etiqueta <form action="URL">, si existe. Si este atributo no existe, los parámetros del formulario se envían a la URL URL que generó el formulario. Este es el caso aquí. Por lo tanto, el botón [Envoyer] debería provocar una solicitud del navegador al URL [http://localhost/form2/formulaire_get.aspx] con una transferencia de los parámetros del formulario. Dado que la página [formulaire_get.aspx] almacena la solicitud recibida, deberíamos saber cómo ha enviado el cliente estos parámetros. Probemos. Hacemos clic en el botón [Envoyer]. Recibimos la siguiente respuesta del navegador:

Es la página inicial, pero se puede observar que el valor «URL» ha cambiado en el campo «[Adresse]» del navegador. Ahora es el siguiente:
http://localhost/form2/formulaire_get.aspx?rdMarie=sí&C1=uno&C2=dos&txtSaisie=programación+asp.net&txtMdp=unMotDePasse&areaSaisie=los+fundamentos+de+la%0D%0Aprogramación+web%0D%0A&cmbValeurs=3&lstSimple=1&lstMultiple=2&lstMultiple=4&btnEnvoyer=Enviar&secret=uneValeur
Se observa que las opciones seleccionadas en el formulario aparecen en el campo «URL». Veamos el contenido del archivo «[request.txt]», que ha almacenado la solicitud del 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
Aparece una solicitud HTTP bastante similar a la que había realizado inicialmente el navegador al solicitar el documento sin enviar parámetros. Hay dos diferencias:
Los parámetros del formulario se han añadido al final de la URL del documento, en el formato ?param1=val1¶m2=val2&... | |
El cliente indica mediante este encabezado «HTTP» el «URL» del documento que estaba visualizando cuando realizó la solicitud |
Analicemos más detenidamente cómo se han pasado los parámetros en el comando GET URL?param1=valor1¶m2=valor2&... HTTP/1.1, donde parami son los nombres de los controles del formulario web y valeuri los valores asociados a ellos. A continuación presentamos una tabla de tres columnas:
- columna 1: recoge la definición de un control HTML del ejemplo
- columna 2: muestra cómo se visualiza este control en un navegador
- columna 3: muestra el valor enviado al servidor por el navegador para el control de la columna 1, tal y como aparece en la solicitud GET del ejemplo
control HTML | Aspecto antes de la validación | valor(es) devuelto(s) |
<input type="radio" value="sí" name="rdMarie" />Sí <input type="radio" checked value="no" name="rdMarie" />No | rdMarie=sí - el valor del atributo value del botón seleccionado por el usuario. | |
<input type="checkbox" value="uno" name="C1" />1 <input type="checkbox" checked value="dos" name="C2" />2 <input type="checkbox" value="tres" name="C3" />3 | C1=uno C2=dos - valores de los atributos value de las casillas marcadas por el usuario | |
<input type="text" maxlength="30" value="algunas palabras" name="txtSaisie" /> | txtEntrada=programación+asp.net - texto introducido por el usuario en el campo de entrada. Los espacios se han sustituido por el signo + | |
<input type="password" maxlength="12" size="12" value="unaContraseña" name="txtMdp" /> | txtMdp=estoesecreto - texto introducido por el usuario en el campo de entrada. El texto realmente escrito era «estoessecreto». El último carácter se perdido porque el atributo maxlength="12" limitaba el número de caracteres a 12. | |
<textarea name="areaSaisie"> línea1 línea2</textarea> | ![]() | areaSaisie=las+bases+de+ la%0D%0A programación+web - texto introducido por el usuario en el campo de entrada. %OD%OA es el marcador de fin de línea. Los espacios se han sustituidos por el signo + |
<select name="cmbValeurs"> <option value="1">opción1 </option> <option value="2" selected>opción 2 </option> <option value="3">opción 3 </option> </select> | cmbValores=3 - valor seleccionado por el usuario en la lista de selección ú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 elegido por el usuario en la lista de selección ú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">múltiplo 4 </option> <option value="5">múltiplo 5 </option> </select> | ![]() | lstMultiple=2 lstMultiple=4 - valores seleccionados por el usuario en la lista de selección múltiple |
<input type="submit" value="Enviar" name="btnEnviar" /> | btnEnvoyer=Enviar - nombre y atributo value del botón que se ha utilizado para enviar los datos del formulario al servidor | |
<input type="hidden" name="secret" value="unValor" /> | secret=unValor - atributo value del campo oculto |
Cabe preguntarse qué ha hecho el servidor con los parámetros que se le han pasado. En realidad, nada. Al recibir la orden
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
El servidor web ha transmitido los parámetros de URL a los documentos [http://localhost/form2/formulaire_get.aspx] y c.a.d, que son los que creamos inicialmente. No hemos escrito ningún código para recuperar y procesar los parámetros que nos envía el cliente. Por lo tanto, todo ocurre como si la solicitud del cliente fuera simplemente:
Por este motivo, al hacer clic en nuestro botón [Envoyer], hemos obtenido la misma página que la obtenida inicialmente al solicitar el URL [http://localhost/form2/formulaire_get.aspx] sin parámetros.
5.3.2. Método POST
El documento HTML está ahora configurado para que el navegador utilice el método POST para enviar los valores del formulario al servidor web. Para ello, copiamos el archivo [formulaire_get.aspx] en [formulaire_post.aspx] y modificamos únicamente la etiqueta <form> en [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">
No es necesario cambiar el controlador [formulaire_get.aspx.vb], así que lo dejamos tal y como está. Solicitamos el nuevo documento a través de URL [http://localhost/form2/formulaire_post.aspx], rellenamos el formulario igual que en el método GET y enviamos los parámetros al servidor con el botón [Envoyer]. Recibimos del servidor la siguiente página de respuesta:

Por lo tanto, obtenemos el mismo resultado que con los métodos GET y c.a.d: la página inicial. Cabe destacar una diferencia: en el campo [Adresse] del navegador no aparecen los parámetros transmitidos. Ahora, veamos la solicitud enviada por el cliente y que se ha almacenado en el archivo [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
Aparecen novedades en la consulta HTTP del cliente:
La consulta GET ha dado paso a la consulta POST. Los parámetros ya no aparecen en esta primera línea de la consulta. Se puede observar que ahora se sitúan después de la consulta HTTP, tras una línea en blanco. Su codificación es idéntica a la que tenían en la consulta GET. | |
número de caracteres «enviados», c.a.d. El número de caracteres que deberá leer el servidor web tras recibir los encabezados HTTP para recuperar el documento que le envía el cliente. El documento en cuestión es, en este caso, la lista de valores del formulario. | |
especifica el tipo de documento que el cliente enviará tras los encabezados HTTP. El tipo [application/x-www-form-urlencoded] indica que se trata de un documento que contiene valores de formulario. |
Existen dos métodos para transmitir datos a un servidor web: GET y POST. ¿Hay algún método mejor que el otro? Hemos visto que, si los valores de un formulario se enviaban desde el navegador mediante el método GET, el navegador mostraba en su campo Adresse la URL solicitada en el formato URL?param1=val1¶m2=val2&.... Esto puede considerarse una ventaja o un inconveniente:
- una ventaja si se quiere permitir al usuario añadir este URL configurado a sus favoritos
- un inconveniente si no queremos que el usuario tenga acceso a cierta información del formulario, como, por ejemplo, los campos ocultos
A partir de ahora, utilizaremos casi exclusivamente el método POST en nuestros formularios.
5.4. Procesamiento en el servidor de los valores de un formulario
5.4.1. Presentación del ejemplo
Ahora que hemos establecido la relación entre la etiqueta HTML <form method="GET/POST" ...> y la forma en que el navegador envía los valores del formulario, sabemos cómo recuperarlos en el lado del servidor. La respuesta la encontramos en el capítulo anterior:
- si el método de la etiqueta <form> es GET, los valores de los parámetros se recuperarán en la colección [Request.QueryString]
- si el método de la etiqueta <form> es POST, los valores de los parámetros «enviados» se recuperarán en la colección [Request.Form]. Aquí hay que hacer una aclaración. La etiqueta <form> puede especificar, mediante el atributo [action], la URL de destino de GET o de POST. Esta URL puede configurarse perfectamente tanto si se trata de un GET como de un POST, con el formato action="url?param1=val1¶m2=val2&..". Estos parámetros se suman entonces a los que se encuentran entre las etiquetas <form> y </form> y que serán objeto de una transferencia al servidor mediante un GET o un POST. Dado que forman parte de la URL de destino, se obtendrán en la colección [Request.QueryString], tanto si se trata de un GET como de un POST.
Ahora vamos a escribir una aplicación MVC con dos vistas:
- la primera vista es el formulario anterior. La llamaremos [vue_formulaire].
- La segunda vista es una página de información que muestra los valores introducidos en la primera página. Un enlace permite volver al formulario. Llamaremos a esta vista [vue_confirmation].
La vista [vue_formulaire] se envía al usuario, quien la rellena y la valida. Podría tener este aspecto justo antes de la validación:

El usuario utiliza el botón [Envoyer] para validar los datos introducidos. A cambio, recibe la siguiente vista [vue_validation]:

5.4.2. El controlador de la aplicación
En el capítulo anterior vimos que podíamos asignar la función de controlador de una aplicación MVC al archivo [global.asax], por el que pasan todas las solicitudes de los clientes. Ya hemos presentado una aplicación MVC construida de esta manera y aquí seguimos el modelo de desarrollo presentado entonces. El archivo [global.asax] tendrá el siguiente aspecto:
Consta de una única línea que hace referencia al controlador ubicado en el archivo [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)
' se recupera la acción que hay que realizar
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' se ejecuta la acción
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
El funcionamiento del controlador es el siguiente:
- espera en la URL de destino una cadena de parámetros que contenga el parámetro [action]. Si este no está presente, se actúa como si se hubiera tenido [action=init] en la cadena de parámetros.
- Solo se reconocen dos acciones:
- init: se envía al cliente el formulario prellenado
- validación: se envía al cliente la página que confirma los datos que ha introducido
- Si la acción no es ninguna de las anteriores, se actúa como si se hubiera incluido [action=init]. También se podría mostrar una página de error.
5.4.3. Procesamiento de la acción «init»
Cuando el controlador procesa la acción «init», debe generar un formulario prellenado. La página [formulaire.aspx] se encarga de realizar esta tarea. Su código es el siguiente:
<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>
Volvemos a encontrar el código HTML del formulario analizado anteriormente, con algunas diferencias. Se ha modificado el código de la etiqueta <form>:
<form name="formulaire" method="post" action="?action=validation">
- post: los valores introducidos por el usuario y enviados al servidor al pulsar el botón de tipo [submit] se enviarán mediante el método HTTP POST
- acción: la sintaxis action="url" sirve para indicar la URL a la que deben enviarse los valores del formulario. Esta URL puede incluir una cadena de parámetros con el formato param1=val1¶m2=val2&... Esto es lo que se hace aquí, donde pasamos el parámetro [action=validation] para indicar al controlador la acción que debe realizar. Cabe señalar que esta cadena de parámetros no va precedida de una dirección web. El navegador enviará entonces los parámetros del formulario a la dirección que le ha proporcionado dicho formulario. En nuestro ejemplo anterior, esta dirección es [http://localhost/mvcform1]. Por lo tanto, el navegador realizará una solicitud [POST /mvcform1?action=validation] al servidor [localhost].
Se han añadido botones para que el usuario pueda deseleccionar los elementos de las listas [lstSimple] y [lstMultiple]:

Esto se traduce en el siguiente 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>
Al hacer clic en un botón [Raz], se deseleccionan todos los elementos de la lista a la que está asociado. Tomemos como ejemplo la lista [lstMultiple]. Al hacer clic en el botón [Raz] correspondiente, se ejecuta la función JavaScript [raz(lstMultiple)]. Recordemos que el código JavaScript de un documento HTML mostrado por un navegador es ejecutado por ese mismo navegador y no por el servidor. JavaScript es un lenguaje muy completo que permite dotar de un aspecto dinámico a las páginas sin intervención del servidor. La función [raz] es la siguiente:
Esta función recibe un parámetro que es un objeto de JavaScript que representa una lista HTML. Este objeto tiene propiedades y métodos. Una de sus propiedades es [selectedIndex], cuyo valor es el número de la primera opción seleccionada en la lista HTML. Si no hay ninguna, esta propiedad toma el valor -1. Por el contrario, asignar un valor a esta propiedad equivale a seleccionar un nuevo elemento de la lista HTML, y asignarle el valor -1 equivale a no tener ningún elemento seleccionado. Eso es lo que se hace aquí.
Por último, cabe señalar que el código de presentación [formulaire.aspx] no va acompañado de un controlador [formulaire.aspx.vb]. De hecho, no hay ninguna parte dinámica generada por el servidor en el documento HTML, por lo que no es necesario disponer de un controlador.
5.4.4. Procesamiento de la acción «validación»
Cuando el controlador procesa la acción «validación», debe generar una página en la que se enumeren los valores introducidos por el usuario. La página [validation.aspx] se encarga de realizar esta tarea. Visualmente, la página tiene el siguiente aspecto:

Su código HTML es el siguiente:
<%@ 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>
Las partes dinámicas <%=variable%> del documento se calculan mediante el controlador [validation.aspx.vb] asociado:
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
'se recuperan los 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
' se recupera el valor del campo [champ] de la solicitud enviada
' ¿algo?
If Request.Form(champ) Is Nothing Then Return ""
': se recuperan los valores del 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
El cálculo de los valores que se van a mostrar se realiza en el procedimiento [Form_Load]. El valor de un campo «enviado» se obtiene mediante la función getValue(C), donde C es el nombre del campo. Los puntos clave de esta función son los siguientes:
- si C no está en la cadena de parámetros enviada, se devuelve la cadena vacía como valor de C
- en caso contrario, se obtiene la matriz de valores del campo C mediante [Request.Form.GetValues(C)]. Estos se concatenan en una cadena de caracteres con el formato [val1][val2]...[valn], donde [vali] es el valor n.º i del campo C
El campo [areaSaisie] se trata de forma especial. El navegador envía su valor en el formato areaSaisie=línea1\r\nlínea2\r\n... donde \r es el carácter con código ASCII 13 (retorno de carro) y \n el carácter con código ASCII 10 (salto de línea). La función getValue(areaSaisie) es, por tanto, la cadena «línea1\r\nlínea2\r\n...». Esta cadena se divide en líneas mediante el método [Regex.Split]. De este modo, se obtiene una matriz de cadenas {línea1,línea2,...}. Esta matriz se transforma en la cadena «línea1,línea2,...» mediante el método [String.Join]. Es esta última cadena la que se mostrará como valor del campo [areaSaisie]. El objetivo era mostrar cómo se pueden obtener las diferentes líneas de un campo HTML de tipo [TextArea].
5.4.5. Pruebas
Colocamos todos los archivos (global.asax, global.asax.vb, formulaire.aspx, validation.aspx, validation.aspx.vb) en una carpeta <application-path>. Iniciamos el servidor Cassini con los parámetros (<application-path>,/mvcform1). Creamos en la carpeta <application-path> un archivo [default.aspx] vacío y, a continuación, solicitamos la URL [http://localhost/mvcform1]. Dado que [/mvcform1] es la ruta virtual de una carpeta y no de un documento, el servidor web mostrará el documento [default.aspx] si está presente. Por eso lo hemos creado. Antes de mostrarlo, se ejecutará el script [global.asax], que finalmente hará que se muestre la página [formulaire.aspx]. Por eso, el archivo [default.aspx] puede estar vacío.
Supongamos que el formulario validado es el siguiente:

Al pulsar el botón [Envoyer], se muestra la siguiente página:

Fijémonos, en primer lugar, en la URL de la respuesta: [http://localhost/mvcform1/?action=validation]. Se trata del URL del atributo [action] de la etiqueta <form> del formulario [formulaire.aspx]:
<form name="formulaire" method="post" action="?action=validation">
Analicemos uno a uno los valores obtenidos para los distintos campos del formulario:
campo | valor | HTML | comentarios |
rdMarie | sí | <input type="radio" value="sí" name="rdMarie">Sí <input type="radio" checked value="no" name="rdMarie">No | el valor obtenido es el atributo [value] del botón marcado |
C1 | un | <input type="checkbox" value="uno" name="C1">1 | lo mismo |
C2 | dos | <input type="checkbox" marcado value="dos" name="C2">2 | lo mismo |
C3 | <input type="checkbox" value="tres" name="C3">3 | El usuario no ha marcado esta casilla. Por lo tanto, el navegador no ha enviado su valor. En el código, la condición [Request.Form("C3") is Nothing] se ha cumplido. | |
txtSaisie | Programación asp.net | <input type="text" ... name="txtSaisie"> | el valor obtenido es el texto que figura en el campo de entrada en el momento de la validación |
txtMdp | mdp | <input type="password" ...name="txtMdp"> | ídem |
areaSaisie | Fundamentos de la programación web | <textarea name="areaSaisie"> ...</textarea> | ídem |
cmbValeurs | 3 | <select name="cmbValeurs"> ... <option value="3">opción 3</option> </select> | el valor obtenido es el atributo [value] de la opción seleccionada |
lstSimple | 3 | <select size="3" name="lstSimple"> .... <option value="3">lista3</option> ... </select> | ídem |
lstMultiple | 2 4 | <select multiple size="3" name="lstMultiple"> ... <option value="2">multiple2 </option> ... <option value="4">multiple4 </option> ... </select> | los valores obtenidos son los de los atributos [value] de las opciones seleccionadas |
secreto | uneValeur | <input type="hidden" name="secret" value="unValor"> | el valor obtenido es el atributo [value] del campo oculto |
Ahora centrémonos en las listas. Supongamos que, en el momento de la validación, el estado del formulario es el siguiente:

- la opción [choix1] está seleccionada en el comboBox
- y no hay ninguna opción seleccionada en las otras dos listas. Para conseguirlo, se han utilizado los botones [Raz].
Esta es la página que se muestra tras la validación:

Cuando no se selecciona ningún valor en una lista, el navegador no envía ningún parámetro para ella. En el código de [validation.aspx.vb], las expresiones [Request.Form("lstSimple")] y [Request.Form("lstMultiple")] son, por lo tanto, iguales a la constante [Nothing], de ahí el resultado que se muestra arriba.
5.5. Mantener el estado de una página
5.5.1. Mantener el estado de una página con una sesión
Duplicamos toda la aplicación anterior en una nueva carpeta. Añadimos un enlace en la página [validation.aspx] que permite al usuario volver al formulario:

La modificación que hay que realizar en la página [validation.aspx] consiste en añadir el enlace:
.....
<TR>
<TD width="84">secret</TD>
<TD><%=secret%></TD>
</TR>
</TABLE>
<P>
<a href="?action=formulaire">Retour au formulaire</a>
</P>
</body>
</HTML>
El atributo [href] del enlace tiene como valor una URL parametrizada con un único parámetro, [action=formulaire], lo que permite al servidor saber que debe mostrar el formulario tal y como estaba cuando se validó. Por lo tanto, existe una diferencia con la acción [init], que muestra un formulario predefinido. La URL parametrizada [?action=formulaire], en realidad, no tiene URL. Por lo tanto, esta será la misma que la que permitió mostrar la página de validación. Si recordamos el estudio anterior, esta es la URL de la carpeta de la aplicación. Por lo tanto, la solicitud pasará por el controlador. Este debe procesar ahora la acción [formulaire]. El código de [global.asax.vb] se modifica de la siguiente manera:
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' se recupera la acción que hay que realizar
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' se ejecuta la acción
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
En el caso de que la acción sea «formulario», basta con enviar la solicitud a la página [formulaire.aspx]. Sabemos que esta página muestra un formulario predefinido en el que no hay ninguna parte variable. Por lo tanto, esta página no puede mostrar el formulario con los valores que tenía cuando se validó. Lo que queremos poner de relieve aquí es precisamente este punto. Si todos los archivos de la aplicación se han colocado en <application-path>, iniciamos Cassini con los parámetros (<application-path>,/mvcform2) y, a continuación, solicitamos la URL [http://localhost/mvcform2]. Obtenemos la siguiente página (vista parcial):

Rellenamos el formulario de la siguiente manera y, a continuación, lo validamos:

Aparece la siguiente página de confirmación:

Utilizamos el enlace [Retour au formulaire] que aparece (aunque no se muestra) en la página anterior. Obtenemos la siguiente respuesta del servidor:

Observamos que:
- la URL solicitada incluye efectivamente el parámetro action=formulario, tal y como se deseaba
- el formulario que se muestra ha perdido los valores introducidos.
Sabemos por qué no recuperamos los valores introducidos. Si observamos el código del documento [formulaire.aspx], vemos que todo es estático y que, por lo tanto, se ve obligado a mostrar siempre la misma página. Es evidente que tenemos que convertir este código en dinámico. Deberá mostrar los valores validados por el usuario. Pero, ¿dónde almacenarlos?
Recordemos la regla de oro del protocolo sin estado HTTP:
- se solicita la URL [http://localhost/mvcform2] y se recibe una respuesta. Se ha abierto una conexión TCP-IP entre el cliente y el servidor al inicio de la solicitud y se ha cerrado al final de la respuesta.
- El usuario introduce y valida los datos. Se solicita la URL [http://localhost/mvcform2/?action=validation] y se recibe una respuesta. Se ha abierto y cerrado una nueva conexión TCP-IP entre ambos interlocutores.
- El usuario utiliza el enlace [Retour au formulaire]. Se solicita la URL [http://localhost/mvcform2/?action=formulaire] y se recibe una respuesta. Se ha abierto de nuevo una nueva conexión TCP-IP, que posteriormente se ha cerrado, entre los dos interlocutores.
Los ciclos de solicitud-respuesta son independientes entre sí, ya que cada uno de ellos utiliza una nueva conexión TCP-IP. Cuando una aplicación cliente-servidor utiliza una única conexión TCP-IP para una serie de intercambios, el servidor puede identificar a un cliente a través de su conexión. De este modo, puede almacenar información que vinculará a una conexión concreta y, así, realizar un seguimiento de los intercambios. Cuando los intercambios se realizan a través de conexiones diferentes, el servidor no puede identificar a un cliente con una conexión. Se necesita otro método. En el capítulo anterior presentamos uno de ellos: el mecanismo de sesión. Este permite que los ciclos de solicitud-respuesta almacenen información en un objeto [Session] accesible para todos los ciclos sucesivos.
Ahora que tenemos una aplicación MVC con sesión, ya no podemos utilizar el archivo [global.asax] como controlador, tal y como se mostró en el capítulo anterior. La función de controlador de la aplicación debe recaer en una página específica dedicada a ello. En este caso, será la página [main.aspx]. Procederemos de la siguiente manera:
- cuando el usuario valide sus datos (acción=validación), el controlador [main.aspx.vb] los almacenará en la sesión actual antes de mostrar la página de validación.
- Cuando sea necesario mostrar el formulario con los valores introducidos (acción=formulario), el controlador [main.aspx.vb] los recuperará de la sesión y los colocará en el contexto antes de mostrar el formulario.
5.5.2. El nuevo controlador de la aplicación
El controlador de aplicación está formado por los dos archivos [main.aspx, main.aspx.vb]:
[main.aspx]
[main.aspx.vb]
Imports System.Collections.Specialized
Imports Microsoft.VisualBasic
Public Class main
Inherits System.Web.UI.Page
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' se recupera la acción que hay que realizar
Dim action As String
If Request.QueryString("action") Is Nothing Then
action = "init"
Else
action = Request.QueryString("action").ToString.ToLower
End If
' se ejecuta la acción
Select Case action
Case "init"
' se muestra el formulario prellenado
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
Case "validation"
' se muestra la página de confirmación tras guardar los valores enviados en la sesión
Session.Item("formulaire") = Request.Form
Server.Transfer("validation.aspx", True)
Case "formulaire"
' se muestra el formulario con los valores tomados de la sesión
Context.Items("formulaire") = Session.Item("formulaire")
Server.Transfer("formulaire.aspx", True)
Case Else
' se muestra el formulario prellenado
Context.Items("formulaire") = initForm()
Server.Transfer("formulaire.aspx", True)
End Select
End Sub
Private Function initForm() As NameValueCollection
' se inicializa el formulario
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
Aquí se aprecia la esencia de la estructura del controlador de aplicación analizado anteriormente, con las siguientes diferencias:
- el trabajo del controlador se realiza en el procedimiento [Form_Load]
- en el caso de la acción [validation], los valores del formulario presentes en [Request.Form] se almacenan en la sesión asociada a la clave «formulario». A continuación, la ejecución se transfiere a la página [validation.aspx], que mostrará dichos valores.
- En el caso de las demás acciones, la ejecución se transfiere en todos los casos a la página [formulaire.aspx]. Esta espera en su contexto una clave «formulario» que se asociará a un objeto del tipo [Request.form], c.a.d o del tipo [NameValueCollection]. Este objeto debe contener la colección de valores de los campos del formulario.
- En el caso de que la acción sea [init] o una acción no reconocida, la colección de valores se construye de forma arbitraria mediante la función [initForm].
- En el caso de que la acción sea [formulaire], esta colección es la colección [Request.Form] que había sido introducida en la sesión por la acción [validation]
5.5.3. El nuevo formulario
Dado que la aplicación ya no muestra el mismo contenido en el formulario, este debe generarse dinámicamente. La nueva página [formulaire.aspx] queda así:
<%@ 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>
Comentemos las variables dinámicas que aparecen en el código HTML:
variable | función |
tendrá el valor «checked» si hay que marcar el botón de opción [oui]; de lo contrario, tendrá el valor «» | |
lo mismo ocurre con el botón de opción [non] | |
lo mismo para la casilla de selección [C1] | |
Lo mismo para la casilla de selección [C2] | |
Lo mismo ocurre con la casilla de selección [C3] | |
el texto que hay que introducir en el campo [txtSaisie] | |
el texto que se debe introducir en el campo [txtMdp] | |
el texto que se debe introducir en el campo [areaSaisie] | |
el texto HTML de las opciones de la lista desplegable [cmbValeurs] | |
el texto HTML de las opciones de la lista desplegable [lstSimple] | |
el texto HTML de las opciones de la lista desplegable [lstMultiple] | |
Los valores de estas variables los calcula el controlador de la página [formulaire.aspx.vb]:
Imports Microsoft.VisualBasic
Imports System.Collections.Specialized
Public Class formulaire
Inherits System.Web.UI.Page
' campos fijos del formulario
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 del formulario
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
' se recupera la solicitud anterior de la sesión
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
' se prepara la página que se va a mostrar
' botones de opción
rdouichecked = ""
rdnonchecked = "checked"
If isEqual(form("rdMarie"), "oui") Then
rdouichecked = "checked"
rdnonchecked = ""
End If
' casillas de selección
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 entrada
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
' genera el código HTML de las opciones de una etiqueta <select>
' valores: tabla de valores de las opciones de la etiqueta
' etiquetas: tabla de etiquetas de las opciones de la etiqueta
' selecciones: opciones que se deben seleccionar
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' se recorre la lista de valores de las opciones
For iValeur = 0 To valeurs.Length - 1
' se comprueba si el valor actual debe seleccionarse
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' se incorpora el código HTML de la opción
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' se devuelve el resultado
Return toString
End Function
Private Function isEqual(Byval champ As Object, ByVal valeur As String) As Boolean
' devuelve «verdadero» si el campo es igual al valor
If champ Is Nothing OrElse champ.ToString <> valeur Then
Return false
Else
Return true
End If
end function
End Class
Cuando la página [formulaire.aspx] comienza a ejecutarse, encuentra en su contexto una clave «formulario» asociada a la colección de valores de los campos que debe mostrar.
' se recupera la consulta anterior de la sesión
Dim form As NameValueCollection
If Not Context.Items("formulaire") Is Nothing Then
form = Context.Items("formulaire")
Else
form = New NameValueCollection
End If
Cabe preguntarse por qué se comprueba que [Context.Items("formulaire")] existe. De hecho, el controlador asigna un valor a este objeto en todos los casos. Sin embargo, nada impide que el cliente solicite directamente la página [formulaire.aspx] sin pasar por el controlador. Si fuera así, el código anterior funcionaría con una colección de valores vacía, pero no se produciría ningún «bloqueo».
El código recorre la colección de valores que ha recibido para calcular todas las variables dinámicas de la página HTML que tiene asociada. Aunque es extenso, este código no es especialmente complicado, por lo que dejamos que el lector se sumerja en él para no alargar demasiado esta explicación. Sin embargo, nos detendremos en cómo se genera el código HTML a partir de las tres listas de tipo [select]. Este código se genera mediante la siguiente función:
Private Function getOptions(ByRef valeurs() As String, ByRef libelles() As String, ByRef sélections() As String) As String
' devuelve el código HTML de las opciones de una etiqueta <select>
' valores: matriz de valores de las opciones de la etiqueta
' etiquetas: matriz de etiquetas de las opciones de la etiqueta
' selecciones: opciones que se deben seleccionar
Dim iValeur As Integer
Dim iSelection As Integer
Dim selected As String
Dim toString As String = ""
' se recorre la lista de valores de las opciones
For iValeur = 0 To valeurs.Length - 1
' se comprueba si el valor actual debe seleccionarse
selected = "" : iSelection = 0
Do While iSelection < sélections.Length And selected = ""
If valeurs(iValeur) = sélections(iSelection) Then selected = "selected"
iSelection += 1
Loop
' se incorpora el código HTML de la opción
toString += "<option " + selected + " value='" + valeurs(iValeur) + "'> " _
+ libelles(iValeur) + "</option>" + ControlChars.CrLf
Next
' se devuelve el resultado
Return toString
End Function
Recordemos que las opciones de una etiqueta <select> corresponden al siguiente código HTML:
Por lo tanto, para cada opción hay que generar tres datos:
- el valor de la opción en el atributo [value]
- el texto de la opción entre las etiquetas <option> y </option>
- la palabra clave [selected] si la opción debe seleccionarse de la lista
Para generar estos tres datos para cada una de las opciones, la función [getOptions] recibe tres valores:
- la tabla de valores de las opciones en [valeurs]
- la tabla de textos de las opciones en [libelles]
- la tabla de valores a seleccionar en [sélections]
5.5.4. La página de validación
La página de validación no sufre cambios:
[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
'se recuperan los 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")
' se guardan en la sesión
'Session("formulario") = Request.Form
End Sub
Private Function getValue(ByVal champ As String) As String
' se recupera el valor del campo [champ] de la solicitud enviada
' ¿algo?
If Request.Form(champ) Is Nothing Then Return ""
' se recuperan los valores del 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. Las pruebas
Los archivos [main.aspx, main.aspx.vb,formulaire.aspx,formulaire.aspx.vb, validation.aspx, validation.aspx.vb] se colocan en <ruta-de-la-aplicación> y se inicia Casini con los parámetros (<ruta-de-la-aplicación>,/mvcform3). A continuación, solicitamos la URL [http://localhost/mvcform3/main.aspx]. Obtenemos el formulario preinicializado:

Rellenamos el formulario de la siguiente manera:

Utilizamos el botón [Envoyer] que aparece arriba. Obtenemos la siguiente respuesta del servidor:

Utilizamos el enlace [Retour au formulaire] que aparece más arriba para volver al formulario. Obtenemos la siguiente respuesta nueva:

Efectivamente, volvemos a ver el formulario tal y como lo habíamos enviado.
5.5.6. Conclusión
El ejemplo anterior nos ha mostrado que es posible mantener el estado de una página a lo largo de los ciclos de solicitud-respuesta entre el cliente y el servidor. Sin embargo, esta tarea no es sencilla. Veremos en un capítulo posterior que, con ASP.NET, es posible dejar que el servidor restablezca por sí mismo el estado de una página.



