Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
por Microsoft
En la tercera iteración, añadimos validación básica de formularios. Evitamos que los usuarios envíen un formulario sin completar los campos de formulario obligatorios. También validamos las direcciones de correo electrónico y los números de teléfono.
Creación de una aplicación de ASP.NET MVC de administración de contactos (VB)
En esta serie de tutoriales, creamos una aplicación completa de administración de contactos de principio a fin. La aplicación Contact Manager le permite almacenar información de contacto (nombres, números de teléfono y direcciones de correo electrónico) para obtener una lista de personas.
Compilamos la aplicación en varias iteraciones. Con cada iteración, mejoramos gradualmente la aplicación. El objetivo de este enfoque de iteración múltiple es permitirle comprender el motivo de cada cambio.
Iteración n.º 1: Crear la aplicación. En la primera iteración, creamos el Administrador de contactos de la manera más sencilla posible. Agregamos compatibilidad con operaciones básicas de base de datos: Crear, Leer, Actualizar y Eliminar (CRUD).
Iteración n.º 2: Hacer que la aplicación tenga un buen aspecto. En esta iteración, mejoramos la apariencia de la aplicación modificando la página maestra de vista predeterminada de ASP.NET MVC y la hoja de estilos en cascada.
Iteración n.º 3: Añadir una validación de formulario. En la tercera iteración, añadimos validación básica de formularios. Evitamos que los usuarios envíen un formulario sin completar los campos de formulario obligatorios. También validamos las direcciones de correo electrónico y los números de teléfono.
Iteración n.º 4: Hacer que la aplicación tenga un acoplamiento flexible. En esta cuarta iteración, aprovechamos varios patrones de diseño de software para facilitar el mantenimiento y modificación de la aplicación Contact Manager. Por ejemplo, refactorizamos la aplicación para usar el patrón Repositorio y el patrón de inserción de dependencias.
Iteración n.º 5: Crear pruebas unitarias. En la quinta iteración, hacemos que la aplicación sea más fácil de mantener y modificar agregando pruebas unitarias. Simulamos nuestras clases de modelo de datos y compilamos pruebas unitarias para nuestros controladores y lógica de validación.
Iteración n.º 6: Utilizar el desarrollo mediante pruebas. En esta sexta iteración, añadimos una nueva funcionalidad a nuestra aplicación escribiendo primero pruebas unitarias y escribiendo código en las pruebas unitarias. En esta iteración, agregamos grupos de contactos.
Iteración n.º 7: Agregar funcionalidad de Ajax. En la séptima iteración, mejoramos la capacidad de respuesta y el rendimiento de nuestra aplicación agregando compatibilidad con Ajax.
Esta iteración
En esta segunda iteración de la aplicación Contact Manager, agregamos validación básica de formularios. Evitamos que las personas envíen un contacto sin especificar valores para los campos de formulario obligatorios. También validamos números de teléfono y direcciones de correo electrónico (vea la figura 1).
Figura 01: Un formulario con validación (haga clic para ver la imagen a tamaño completo)
En esta iteración, añadimos la lógica de validación directamente a las acciones del controlador. En general, esta no es la manera recomendada de agregar validación a una aplicación ASP.NET MVC. Un enfoque mejor es colocar la lógica de validación de una aplicación en una capa de servicio independiente. En la siguiente iteración, refactorizamos la aplicación Contact Manager para que la aplicación sea más fácil de mantener.
En esta iteración, para simplificar las cosas, se escribe todo el código de validación manualmente. En lugar de escribir el código de validación, podríamos aprovechar un marco de validación. Por ejemplo, puede usar el bloque de aplicación de validación (VAB) de Microsoft Enterprise Library para implementar la lógica de validación de su aplicación ASP.NET MVC. Para más información sobre el bloque de aplicación de validación, consulte:
http://msdn.microsoft.com/library/dd203099.aspx
Añadir validación a la vista Create
Empecemos por añadir lógica de validación a la vista Create. Afortunadamente, como hemos generado la vista Create con Visual Studio, la vista Create ya contiene toda la lógica de interfaz de usuario necesaria para mostrar los mensajes de validación. La vista Create está contenida en la lista 1.
Lista 1: \Views\Contact\Create.aspx
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of ContactManager.Contact)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ValidationSummary() %>
<% Using Html.BeginForm()%>
<fieldset>
<legend>Create New Contact</legend>
<p>
<label for="FirstName">First Name:</label>
<%= Html.TextBox("FirstName") %>
<%= Html.ValidationMessage("FirstName", "*") %>
</p>
<p>
<label for="LastName">Last Name:</label>
<%= Html.TextBox("LastName") %>
<%= Html.ValidationMessage("LastName", "*") %>
</p>
<p>
<label for="Phone">Phone:</label>
<%= Html.TextBox("Phone") %>
<%= Html.ValidationMessage("Phone", "*") %>
</p>
<p>
<label for="Email">Email:</label>
<%= Html.TextBox("Email") %>
<%= Html.ValidationMessage("Email", "*") %>
</p>
<p class="submit">
<input type="submit" value="Create" />
</p>
</fieldset>
<% End Using %>
</asp:Content>
La clase error de validación de campo se usa para dar estilo a la salida representada por el asistente Html.ValidationMessage(). La clase input-validation-error se usa para dar estilo al cuadro de texto (entrada) representado por el asistente Html.TextBox(). La clase validation-summary-errors se usa para dar estilo a la lista desordenada representada por el asistente Html.ValidationSummary().
Nota:
Puede modificar las clases de hoja de estilos descritas en esta sección para personalizar la apariencia de los mensajes de error de validación.
Añadir lógica de validación a la acción Create
Ahora mismo, la vista Create nunca muestra mensajes de error de validación porque no hemos escrito la lógica para generar ningún mensaje. Para mostrar mensajes de error de validación, debe agregar los mensajes de error a ModelState.
Nota:
El método UpdateModel() agrega mensajes de error a ModelState automáticamente cuando se produce un error al asignar el valor de un campo de formulario a una propiedad. Por ejemplo, si intenta asignar la cadena "apple" a una propiedad BirthDate que acepta valores DateTime, el método UpdateModel() agregará un error a ModelState.
El método Create() modificado de la lista 2 contiene una nueva sección que valida las propiedades de la clase Contact antes de insertar el nuevo contacto en la base de datos.
Lista 2: Controllers\ContactController.vb (crear con validación)
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
' Validation logic
If contactToCreate.FirstName.Trim().Length = 0 Then
ModelState.AddModelError("FirstName", "First name is required.")
End If
If contactToCreate.LastName.Trim().Length = 0 Then
ModelState.AddModelError("LastName", "Last name is required.")
End If
If (contactToCreate.Phone.Length > 0 AndAlso Not Regex.IsMatch(contactToCreate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.")
End If
If (contactToCreate.Email.Length > 0 AndAlso Not Regex.IsMatch(contactToCreate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.")
End If
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_entities.AddToContactSet(contactToCreate)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
La sección de validación aplica cuatro reglas de validación distintas:
- La propiedad FirstName debe tener una longitud superior a cero (y no puede estar formada únicamente por espacios)
- La propiedad LastName debe tener una longitud superior a cero (y no puede estar formada únicamente por espacios)
- Si la propiedad Phone tiene un valor (tiene una longitud superior a 0), la propiedad Phone debe coincidir con una expresión regular.
- Si la propiedad Email tiene un valor (tiene una longitud superior a 0), la propiedad Email debe coincidir con una expresión regular.
Cuando se produce una infracción de las reglas de validación, se agrega un mensaje de error a ModelState con ayuda del método AddModelError(). Cuando agrega un mensaje a ModelState, proporciona el nombre de una propiedad y el texto de un mensaje de error de validación. Este mensaje de error se muestra en la vista mediante los métodos asistentes Html.ValidationSummary() y Html.ValidationMessage().
Una vez ejecutadas las reglas de validación, se comprueba la propiedad IsValid de ModelState. La propiedad IsValid devuelve false cuando se ha agregado algún mensaje de error de validación a ModelState. Si la validación falla, se vuelve a mostrar el formulario Create con los mensajes de error.
Nota:
Obtuve las expresiones regulares para validar el número de teléfono y la dirección de correo electrónico del repositorio de expresiones regulares en http://regexlib.com.
Añadir lógica de validación a la acción Edit
La acción Edit() actualiza un Contacto. La acción Edit() debe realizar exactamente la misma validación que la acción Create(). En lugar de duplicar el mismo código de validación, deberíamos refactorizar el controlador Contact para que tanto las acciones Create() como Edit() llamen al mismo método de validación.
La clase de controlador Contact modificada figura en la lista 3. Esta clase tiene un nuevo método ValidateContact() que se llama dentro de las acciones Create() y Edit().
Lista 3: Controllers\ContactController.vb
Public Class ContactController
Inherits System.Web.Mvc.Controller
Private _entities As New ContactManagerDBEntities()
Protected Sub ValidateContact(contactToValidate As Contact)
If contactToValidate.FirstName.Trim().Length = 0 Then
ModelState.AddModelError("FirstName", "First name is required.")
End If
If contactToValidate.LastName.Trim().Length = 0 Then
ModelState.AddModelError("LastName", "Last name is required.")
End If
If (contactToValidate.Phone.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.")
End If
If (contactToValidate.Email.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.")
End If
End Sub
'
' GET: /Contact
Function Index() As ActionResult
Return View(_entities.ContactSet.ToList())
End Function
'
' GET: /Contact/Create
Function Create() As ActionResult
Return View()
End Function
'
' POST: /Contact/Create
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
' Validation logic
ValidateContact(contactToCreate)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_entities.AddToContactSet(contactToCreate)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
'
' GET: /Contact/Edit/5
Function Edit(ByVal id As Integer) As ActionResult
Dim contactToEdit = (from c in _entities.ContactSet _
where c.Id = id _
select c).FirstOrDefault()
Return View(contactToEdit)
End Function
'
' POST: /Contact/Edit/5
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal contactToEdit As Contact) As ActionResult
' Validation logic
ValidateContact(contactToEdit)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
Dim originalContact = (from c in _entities.ContactSet _
where c.Id = contactToEdit.Id _
select c).FirstOrDefault()
_entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
'
' GET: /Contact/Delete/5
Function Delete(ByVal id As Integer) As ActionResult
Dim contactToDelete = (from c in _entities.ContactSet _
where c.Id = id _
select c).FirstOrDefault()
Return View(contactToDelete)
End Function
'
' POST: /Contact/Delete/5
<AcceptVerbs(HttpVerbs.Post)> _
Function Delete(ByVal contactToDelete As Contact) As ActionResult
Try
Dim originalContact = (from c in _entities.ContactSet _
where c.Id = contactToDelete.Id _
select c).FirstOrDefault()
_entities.DeleteObject(originalContact)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
Resumen
En esta iteración, hemos agregado la validación básica de formularios a nuestra aplicación Contact Manager. Nuestra lógica de validación impide que los usuarios envíen un nuevo contacto o editen un contacto existente sin proporcionar valores para las propiedades FirstName y LastName. Además, los usuarios deben facilitar números de teléfono y direcciones de correo electrónico válidos.
En esta iteración, hemos agregado la lógica de validación a nuestra aplicación Contact Manager de la forma más sencilla posible. Sin embargo, mezclar nuestra lógica de validación en la lógica de nuestro controlador nos creará problemas a largo plazo. Nuestra aplicación será más difícil de mantener y modificar con el tiempo.
En la próxima iteración, refactorizaremos nuestra lógica de validación y de acceso a la base de datos fuera de nuestros controladores. Aprovecharemos varios principios de diseño de software para permitirnos crear una aplicación más flexible y fácil de mantener.