[ASP.NET MVC] Validación modelo Entity Framework

En este artículo vamos a ver como validar los elementos de nuestro modelo de datos cuando implementamos las acciones Create y Edit. Existen dos tipos de validación que se pueden aplicar; validaciones en el lado servidor, y en el lado cliente. Para el primero de los casos vamos a usar Data Annotations. Las Data Annotations son atributos que nos permiten describir reglas que deben cumplir las propiedades de nuestro modelo:

  • Required – Indica que la propiedad es un campo requerido
  • DisplayName – Define el texto que queremos mostrar al validar los campos
  • StringLength – Define la longitud máxima para un campo de tipo string
  • Range – Da un rango de valores(máximo y mínimo) para un campo numérico
  • Bind – Permite excluir o incluir campos cuando enlazamos parámetros o valores con las propiedades del modelo
  • ScaffoldColumn – Permite ocultar campos del formulario de edición

 

En este caso partimos de una aplicación de tipo ASP.NET MVC 2 Web Application llamada ValidationApp, que tiene una base de datos que consta de una tabla llamada Team cuyos campos son los siguientes:

image

Creamos el modelo que nos permita interactuar con dicha base de datos que será de tipo ADO.NET Entity  Data Model, y que llamaremos TeamModel. Cuando trabajamos con modelos de tipo Entity Framework, las clases de dichos modelos se autogeneran, por lo que si añadimos las validaciones directamente sobre ellas, estas se sobrescribirían al actualizar el modelo desde la base de datos. En este caso lo que hacemos es definir clases parciales de nuestros modelos, en los que configuraremos las validaciones mediante el uso del atributo [MetadataType].

Creamos una clase llamada Team.cs que nos permitirá validar los valores de nuestro modelo Team. Para ello hacemos clic con el botón derecho sobre la carpeta Models y seleccionamos Add > class. Dentro de dicha clase:

1. Añadimos las siguientes referencias:

  1. using System.ComponentModel;
  2. using System.ComponentModel.DataAnnotations;
  3. using System.Web.Mvc;

3. Creamos la clase de validación de los metadatos con los requisitos de validación para cada uno de los campos

  1. [Bind(Exclude=«TeamID»)]
  2.         public class TeamMetaData
  3.         {
  4.             [Required(ErrorMessage=«Introduce el nombre del equipo»)]
  5.             public object TeamName { get; set; }
  6.  
  7.             [DisplayName(«Nombre del pabellón de juego»)]
  8.             [Required(ErrorMessage = «Introduce el nombre del pabellón»)]
  9.             public object TeamPlace { get; set; }
  10.  
  11.             [DisplayName(«Nombre del equipo»)]
  12.             [Required(ErrorMessage = «Introduce el nombre de la ciudad»)]
  13.             [StringLength(50,ErrorMessage=«El número de carácteres es demasiado largo»)]
  14.             public object TeamCity { get; set; }
  15.  
  16.         }

3. Indicamos que tipo de metadatos vamos a utilizar:

  1. [MetadataType(typeof(TeamMetaData))]

De forma que el código completo de la clase queda de la siguiente forma:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.ComponentModel;
  6. using System.ComponentModel.DataAnnotations;
  7. using System.Web.Mvc;
  8.  
  9.  
  10. namespace ValidationApp.Models
  11. {
  12.     [MetadataType(typeof(TeamMetaData))]
  13.     public partial class Team
  14.     {
  15.         [Bind(Exclude=«TeamID»)]
  16.         public class TeamMetaData
  17.         {
  18.             [Required(ErrorMessage=«Introduce el nombre del equipo»)]
  19.             public object TeamName { get; set; }
  20.  
  21.             [DisplayName(«Nombre del pabellón de juego»)]
  22.             [Required(ErrorMessage = «Introduce el nombre del pabellón»)]
  23.             public object TeamPlace { get; set; }
  24.  
  25.             [DisplayName(«Nombre del equipo»)]
  26.             [Required(ErrorMessage = «Introduce el nombre de la ciudad»)]
  27.             [StringLength(50,ErrorMessage=«El número de carácteres es demasiado largo»)]
  28.             public object TeamCity { get; set; }
  29.  
  30.         }
  31.     }
  32. }

A continuación creamos las distintas acciones de nuestro controlador y sus vistas correspondientes, como ya hemos visto en otras ocasiones, de forma que podamos implementar operaciones de tipo CRUD con nuestra base de datos.

Finalmente compilamos nuestra aplicación y navegamos hasta /Team/Create. Si intentamos crear un elemento, y este no cumple con los criterios establecidos vemos como se aplican las reglas de validación correspondientes.

image image image

Aunque la el tipo de validación que hemos visto funciona correctamente, existen tres problemas con él:

1. El usuario tiene que esperar a que se envíe el formulario, se valide en el servidor, y se reciba la respuesta en el navegador.

2. El usuario no obtiene inmediatamente feedback cuando se corrige un campo

3. Se gastan recursos de servidor para representar la validación lógica

A continuación vamos a ver como se realizaría la validación en el lado cliente, y las ventajas que esta presenta. Como nuestra clase Team, ya tiene los atributos de validación establecidos, sólo necesitamos añadir algo de javascript a nuestra página Create.aspx para activar la validación en el lado cliente. Para ello abrimos la vista Team/Create.aspx.

Arrastramos a dicha vista los archivos: MicrosoftAjax.js, MicrosoftMvcAjax.js, MicrosoftMvcValidation.js

De forma que se genera el siguiente código:

  1. <script src=»../../Scripts/MicrosoftAjax.js» type=»text/javascript»></script>
  2. <script src=»../../Scripts/MicrosoftMvcAjax.js» type=»text/javascript»></script>
  3. <script src=»../../Scripts/MicrosoftMvcValidation.js» type=»text/javascript»></script>

A continuación añadimos la siguiente línea de código sobre Html.BeginForm:

  1. <%Html.EnableClientValidation();%>

Así quedaría el código de nuestra vista:

  1. <asp:Content ID=»Content2″ ContentPlaceHolderID=»MainContent» runat=»server»>
  2.  
  3.     <h2>Create</h2>
  4.     <script src=»../../Scripts/MicrosoftAjax.js» type=»text/javascript»></script>
  5.     <script src=»../../Scripts/MicrosoftMvcAjax.js» type=»text/javascript»></script>
  6.     <script src=»../../Scripts/MicrosoftMvcValidation.js» type=»text/javascript»></script>
  7.     
  8.     <%Html.EnableClientValidation();%>
  9.     <% using (Html.BeginForm()) {%>
  10.         <%: Html.ValidationSummary(true) %>
  11.  
  12.         <fieldset>
  13.             <legend>Fields</legend>
  14.             
  15.             <div class=»editor-label»>
  16.                 <%: Html.LabelFor(model => model.TeamID) %>
  17.             </div>
  18.             <div class=»editor-field»>
  19.                 <%: Html.TextBoxFor(model => model.TeamID) %>
  20.                 <%: Html.ValidationMessageFor(model => model.TeamID) %>
  21.             </div>
  22.             
  23.             <div class=»editor-label»>
  24.                 <%: Html.LabelFor(model => model.TeamName) %>
  25.             </div>
  26.             <div class=»editor-field»>
  27.                 <%: Html.TextBoxFor(model => model.TeamName) %>
  28.                 <%: Html.ValidationMessageFor(model => model.TeamName) %>
  29.             </div>
  30.             
  31.             <div class=»editor-label»>
  32.                 <%: Html.LabelFor(model => model.TeamPlace) %>
  33.             </div>
  34.             <div class=»editor-field»>
  35.                 <%: Html.TextBoxFor(model => model.TeamPlace) %>
  36.                 <%: Html.ValidationMessageFor(model => model.TeamPlace) %>
  37.             </div>
  38.             
  39.             <div class=»editor-label»>
  40.                 <%: Html.LabelFor(model => model.TeamCity) %>
  41.             </div>
  42.             <div class=»editor-field»>
  43.                 <%: Html.TextBoxFor(model => model.TeamCity) %>
  44.                 <%: Html.ValidationMessageFor(model => model.TeamCity) %>
  45.             </div>
  46.             
  47.             <p>
  48.                 <input type=»submit» value=»Create» />
  49.             </p>
  50.         </fieldset>
  51.  
  52.     <% } %>
  53.  
  54.     <div>
  55.         <%: Html.ActionLink(«Back to List», «Index») %>
  56.     </div>
  57.  
  58. </asp:Content>

Si ejecutamos la aplicación y accedemos a la página /Team/Create, vemos que los mensajes de error aparecen inmediatamente sin tener que esperar a los postbacks. Esto se debe a que ahora la validación se realiza inicialmente en el cliente (mediante el uso de javascript).

Esto es todo lo que necesitamos aplicar para establecer una validación en el lado cliente. En este caso todos los campos son chequeados en el navegador antes de enviar la información a las acciones del controlador, y la respuesta de validación es inmediata.

 

4 comentarios sobre “[ASP.NET MVC] Validación modelo Entity Framework”

  1. Muy útil!!

    La validación del lado del cliente me funciona de maravilla!
    La del lado del servidor me sigue diciendo que no tengo controlada la excepción. ¿Alguna idea del por qué?

  2. Hola Nico,
    Lo más probable es que no hayas hecho referencia a los scripts MicrosoftAjax.js, MicrosoftMvcAjax.js, MicrosoftMvcValidation en el orden correcto. De forma que si intentas ejecutar la validación sin haber implementado antes los scripts de ajax…te saltará una excepción ya que intenta llamar a funciones que todavía no estan «definidas».
    Un saludo

  3. Muchas Gracias por la info!

    Lo traté de implementar utilizando el archivo .emdx de entity framework y cada vez que realizo un pequeño cambio me borra toda la metadata agragada a las propiedades.
    Hay alguna forma de hacerlo más persistente y no tener que cambiarlo cada vez que actualizo ese archivo?

    Gracias de nuevo!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *