validaciondedatosmvc

Una nueva forma de desarrollo de software en general resulta aditiva. Esto quiere decir que los nuevos modelos vienen a agregar una nueva capa de abstracción sobre tecnologías ya existentes que, mientras más grandes se hacen los sistemas, más código se requiere desarrollar. Desde ese punto, una nueva abstracción resulta en el agrupamiento de código y reglas generales para que automaticen y simplifiquen nuestro desarrollo.

MVC es, en un punto, esta abstracción sobre el modelo de desarrollo clásico con ASP.net, dejando muchas de las transacciones, traducciones, traspaso de datos, serializaciones y demás al Framework, y desligando de ese trabajo al desarrollador.

Y, por supuesto, MVC también nos permitirá abstraer las validaciones de datos cuando ingresan a una acción dentro de un controlador.

Asegurando nuestros datos

Generalmente, cuando necesitamos asegurarnos que los datos estén correctamente ingresados por el usuario, solemos recurrir a una validación manual; esto es, escribimos las condiciones por las que debe pasar y cumplir cada uno de los valores de nuestros objetos. Por ejemplo, pensemos en la siguiente validación, que usaremos para manejar los datos de los usuarios que intenten registrarse en nuestro sitio Web.

public class Usuario
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public string Apellido { get; set; }
    public string Email { get; set; }
}

Ahora, asumamos que esta clase es pasada desde una vista hacia una acción en un controlador de MVC. Si decidiéramos validar esta información tendríamos un código similar al siguiente.

[HttpPost]
public ActionResult Index(Usuario modelo)
{
    if (!string.IsNullOrWhiteSpace(modelo.Nombre) &&
        !string.IsNullOrWhiteSpace(modelo.Apellido) &&
        !string.IsNullOrWhiteSpace(modelo.Email))
    {
        //Otras validaciones
    }
    else
    {
        //Error
        ViewBag.Error = "Ocurrieron errores";
    }

    return View(modelo);
}

En el anterior código sólo hacemos una primera validación, para asegurarnos que los campos del modelo incluyan, por lo menos, algún caracter. Pero a esto deberíamos sumarle, por ejemplo, que la cuenta de correo electrónico sea efectivamente una cuenta de correo, o que tanto el nombre como el apellido no superen determinada cantidad de caracteres, u otras validaciones que, posiblemente, se repitan en el transcurso de la construcción de la aplicación.
Además, podemos ver que resulta muy difícil poder discriminar los errores de validación sin contar con una lógica de código más detallada, lo que hará que invirtamos más tiempo de desarrollo del que realmente sería necesario.

@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.Id)

    <div>Nombre de usuario:</div>
    <div>@Html.TextBoxFor(model => model.Nombre)</div>    
    <div>Apellido:</div>
    <div>@Html.TextBoxFor(model => model.Apellido)</div>    
    <div>Email:</div>
    <div>@Html.TextBoxFor(model => model.Email)</div>
    <input type="submit" value="Enviar" />    
    <div>@ViewBag.Error</div>
}

Podemos ver que en la vista sólo podemos tomar lo que hemos colocado en el objeto ViewBag y mostrarlo al usuario. Aunque, como decíamos, no será lo suficientemente detallado como para representar todos los posibles problemas encontrados en la validación.

Es necesario, por lo tanto, mejorar el modelo de validación utilizando las herramientas provistas por esta abstracción.

El error en la validación de datos es mostrado, pero presenta muy poca información hacia el usuario.

Validando mediante decoraciones

Para evitarnos tanto trabajo de código al realizar validaciones, esta capa de abstracción nos provee un conjunto de clases dentro del espacio de nombres System.ComponentModel.DataAnnotations para poder decorar mediante atributos cada una de las propiedades del modelo de datos, y permitirle al framework realizar una validación previa de los datos enviados desde la vista hacia el controlador de forma que, si no se cumplen estas validaciones, podamos tener una lista completa y detallada de las mismas, así como considerar que el modelo enviado es válido o no y actuar en consecuencia.

public class Usuario
{
    public int Id { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage="El nombre no puede estar vacio.")]
    public string Nombre { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "El apellido no puede estar vacio.")]
    public string Apellido { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Se requiere un correo electrónico")]
    [DataType(DataType.EmailAddress)]
    [RegularExpression(@"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$", ErrorMessage = "No es un email válido.")]
    public string Email { get; set; }
}

El primer paso es modificar nuestra clase utilizada como modelo de datos para adicionar, por cada propiedad, su respectiva validación.

En este sentido podemos ver un atributo llamado Required (Requerido) el que especifica si dicho campo, representado luego en la vista, debe sí o sí incluir algún valor. Además, es posible especificar si se permitirá que el campo se encuentre vacío o no, y un mensaje de error, el que será mostrado, si así lo quisiéramos, cuando dicho campo no cumpla con la validación.

Otra posibilidad, no sólo relacionada a campos del tipo texto, es la del uso del atributo decorativo DataType (Tipo de dato). Este atributo nos sirve para especificar cómo debe ser tratado dicho campo, pudiendo elegir de una lista extensa. De esta forma, un campo del tipo EmailAddress (Dirección de correo electrónico) tendrá un tratamiento diferente a uno numérico, de fecha, etcétera.

Finalmente, podemos ver un tipo de validador llamado RegularExpression (Expresión regular) el que nos permitirá especificar, mediante una expresión regular, la forma personalizada de realizar la validación del campo (en el ejemplo, para asegurarse que cumpla con las reglas de un correo electrónico) fallando si no cumpliera con la misma.

Una vez tenemos esta decoración sobre nuestro objeto de datos, será necesario modificar la vista para hacer uso de esta característica.

@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.Id)    
    <div>Nombre de usuario:</div>
    <div>@Html.TextBoxFor(model => model.Nombre)</div>
    <div>@Html.ValidationMessageFor(model => model.Nombre)</div>    
    <div>Apellido:</div>
    <div>@Html.TextBoxFor(model => model.Apellido)</div>
    <div>@Html.ValidationMessageFor(model => model.Apellido)</div>    
    <div>Email:</div>
    <div>@Html.TextBoxFor(model => model.Email)</div>
    <div>@Html.ValidationMessageFor(model => model.Email)</div>
    <input type="submit" value="Enviar" />    
    <div>@Html.ValidationSummary()</div>
}

Como vemos en el código anterior, no sólo modificamos el lugar donde mostrábamos el error sino que además ahora podemos especificar el lugar donde se mostrará el mensaje específico del campo con error de validación.

Al no ingresar texto alguno, todos los campos son marcados con errores de validación.

En la imagen anterior, además, podremos notar dos particularidades. La primera, es que los campos con error se ven marcados (sus bordes en rojo y el fondo en un color más claro), especificando que existe, definitivamente, un error.

Esto se debe a que MVC aplicará, automáticamente, una clase CSS al campo con error. Esta clase es creada por defecto en la hoja de estilo predeterminada cuando un nuevo proyecto MVC es creado.

La segunda particularidad es que en la imagen podemos ver que el primer error mostrado no fue especificado por nosotros. Como en nuestro modelo el campo Id del tipo entero no acepta valores nulos, debido a que el modelo siempre es validado, al no proveerle uno el error es lanzado. La forma más simple de evitar este error será especificando que dicha propiedad permita nulos, como en el siguiente código.

public class Usuario
{
    public int? Id { get; set; }
    ...
    ...</code>

Con todo lo anterior, sólo nos quedará pendiente saber si el modelo es válido o no desde el controlador. De serlo, podremos actuar de determinada forma y de otra si no lo fuese.

[HttpPost]
public ActionResult Index(Usuario modelo)
{
    if (ModelState.IsValid)
    {
        //Acciones con el modelo validado
    }
    return View(modelo);
}

Si el modelo resulta válido, esto es, correcto en todas sus propiedades, el objeto ModelState (Estado del modelo) mediante su propiedad IsValid (Es válido) nos retornará el estado de verdadero; y falso si alguna validación hubiese fallado.

Un paso más allá

Esta forma de trabajo mediante decoraciones en MVC no sólo se reduce a validaciones, sino que podemos también utilizarlas para proveer el texto exacto que deberá mostrarse en la vista mediante las propiedades del modelo.

public class Usuario
{
    public int? Id { get; set; }
    [DisplayName("Nombre:")]
    [Required(AllowEmptyStrings = false, ErrorMessage="El nombre no puede estar vacio.")]
    public string Nombre { get; set; }
    ...
    ...}

El atributo decorativo DisplayName (Nombre a mostrar) cumple la función de especificar el texto que se usará para esta etiqueta. De esta forma, si necesitáramos utilizar el mismo modelo en diferentes lugares de la aplicación y, además de validar sus valores, mostrar una descripción de cada uno, este sería consistente en toda la aplicación.

<code><div>@Html.LabelFor(model => model.Nombre)</div>
<div>@Html.TextBoxFor(model => model.Nombre)</div>
<div>@Html.ValidationMessageFor(model => model.Nombre)</div></code>

Para este caso modificamos el texto escrito sobre la vista para pasar a utilizar la función LabelFor (Etiqueta para), la que tomará el atributo decorativo y lo escribirá en su lugar.

Conclusiones

Muchas veces nos encontramos repitiendo líneas de código en nuestras aplicaciones de forma innecesaria. Líneas, como en el caso de la validación de datos, que deberían ir un paso más adelante que simplemente abstraer las reglas de validación y colocarlas en algún lugar profundo de nuestra aplicación. Esto resulta innecesario, ya que al final terminaremos teniendo la necesidad de darle más mantenimiento a estas validaciones que a las reglas de negocio reales de nuestra aplicación, lo que requerirá, sin dudas, inversión de tiempo y dinero.

Los atributos decorativos de MVC, entonces, nos facilitan una de las tareas, dejándoles a ellos y al framework, el trabajo rutinario, además de tener la seguridad de que los métodos utilizados para estas validaciones son lo suficientemente seguros como para confiar en ellos.

fuente: http://www.dattamagazine.com/validacion-de-datos-mediante-decoracion-en-mvc/

author: Matías Iacono

Validación de datos mediante decoración en MVC
Etiquetado en: