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 Stephen Walther
Stephen Walther explica cómo mostrar mensajes de error de validación personalizados mediante la implementación de la interfaz IDataErrorInfo en una clase de modelo.
El objetivo de este tutorial es explicar un enfoque para realizar la validación en una aplicación ASP.NET MVC. Aprenderá a evitar que alguien envíe un formulario HTML sin proporcionar valores para los campos de formulario necesarios. En este tutorial, aprenderá a realizar una validación mediante la interfaz IErrorDataInfo.
Supuestos
En este tutorial, utilizaré la base de datos MoviesDB y la tabla de base de datos Movies. Esta tabla consta de las siguientes columnas:
| Nombre de la columna | Tipo de datos | Permitir valores NULL |
|---|---|---|
| Identificador | Int | False |
| Título | Nvarchar(100) | False |
| Director | Nvarchar(100) | False |
| DateReleased | DateTime | False |
En este tutorial, uso Microsoft Entity Framework para generar mis clases de modelo de base de datos. La clase Movie generada por Entity Framework se muestra en la figura 1.
Figura 01: Entidad Movie (Haga clic para ver la imagen a tamaño completo)
Nota:
Si desea más información sobre el uso de Entity Framework para generar las clases de modelo de base de datos, consulte mi tutorial titulado Creación de clases de modelo con Entity Framework.
Clase de controlador
Utilizamos el controlador Home para enumerar películas y crear nuevas películas. El código de esta clase se encuentra en la lista 1.
Lista 1 - Controllers\HomeController.vb
Public Class HomeController
Inherits Controller
Private _db As New MoviesDBEntities()
Public Function Index() As ActionResult
Return View(_db.MovieSet.ToList())
End Function
Public Function Create() As ActionResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal movieToCreate As Movie) As ActionResult
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
' Add to database
Try
_db.AddToMovieSet(movieToCreate)
_db.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
La clase de controlador Home de la lista 1 contiene dos acciones Create(). La primera acción muestra el formulario HTML para crear una nueva película. La segunda acción Create() realiza la inserción real de la nueva película en la base de datos. La segunda acción Create() se invoca cuando se envía al servidor el formulario mostrado por la primera acción Create().
Observe que la segunda acción Create() contiene las siguientes líneas de código:
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
La propiedad IsValid devuelve false cuando se produce un error de validación. En ese caso, se vuelve a mostrar la vista Create que contiene el formulario HTML para crear una película.
Creación de una clase parcial
Entity Framework genera la clase Movie. Puede ver el código de la clase Movie si expande el archivo MoviesDBModel.edmx en la ventana Explorador de soluciones y abre el archivo MoviesDBModel.Designer.vb en el Editor de código (vea la figura 2).
Figura 02: Código de la entidad Movie (Haga clic para ver la imagen a tamaño completo)
La clase Movie es una clase parcial. Esto significa que podemos agregar otra clase parcial con el mismo nombre para ampliar la funcionalidad de la clase Movie. Agregaremos nuestra lógica de validación a la nueva clase parcial.
Agregue la clase de la lista 2 a la carpeta Models.
Lista 2 - Models\Movie.vb
Public Partial Class Movie
End Class
Observe que la clase de la lista 2 incluye el modificador partial. Los métodos o propiedades que agregue a esta clase forman parte de la clase Movie generada por Entity Framework.
Incorporación de métodos parciales OnChanging y OnChanged
Cuando Entity Framework genera una clase de entidad, Entity Framework agrega métodos parciales a la clase automáticamente. Entity Framework genera métodos parciales OnChanging y OnChanged que corresponden a cada propiedad de la clase.
En el caso de la clase Movie, Entity Framework crea los métodos siguientes:
- OnIdChanging
- OnIdChanged
- OnTitleChanging
- OnTitleChanged
- OnDirectorChanging
- OnDirectorChanged
- OnDateReleasedChanging
- OnDateReleasedChanged
Se llama al método OnChanging justo antes de cambiar la propiedad correspondiente. Se llama al método OnChanged justo después de cambiar la propiedad.
Puede aprovechar estos métodos parciales para agregar lógica de validación a la clase Movie. La clase Movie de actualización de la lista 3 comprueba que a las propiedades Title y Director se les asignan valores no vacíos.
Nota:
Un método parcial es un método definido en una clase que no es necesario implementar. Si no implementa un método parcial, el compilador quita la firma del método y todas las llamadas al método para que no haya ningún costo en tiempo de ejecución asociado al método parcial. En el editor de Visual Studio Code, puede agregar un método parcial escribiendo la palabra clave partial seguida de un espacio para ver una lista de los parciales que se van a implementar.
Lista 3: Models\Movie.vb
Imports System.ComponentModel
Partial Public Class Movie
Implements IDataErrorInfo
Private _errors As New Dictionary(Of String, String)()
Private Sub OnTitleChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Title", "Title is required.")
End If
End Sub
Private Sub OnDirectorChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Director", "Director is required.")
End If
End Sub
End Class
Por ejemplo, si intenta asignar una cadena vacía a la propiedad Title, se asigna un mensaje de error a un diccionario denominado _errors.
En ese momento, en realidad no sucede nada cuando asigna una cadena vacía a la propiedad Title y se agrega un error al campo _errors privado. Es necesario implementar la interfaz IDataErrorInfo para exponer estos errores de validación en el marco de ASP.NET MVC.
Implementación de la interfaz IDataErrorInfo
La interfaz IDataErrorInfo forma parte de .NET Framework desde la primera versión. Esta interfaz es muy sencilla:
Public Interface IDataErrorInfo
Default ReadOnly Property Item(ByVal columnName As String) As String
ReadOnly Property [Error]() As String
End Interface
Si una clase implementa la interfaz IDataErrorInfo, el marco de ASP.NET MVC usará esta interfaz al crear una instancia de la clase. Por ejemplo, la acción Create() del controlador Home acepta una instancia de la clase Movie:
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal movieToCreate As Movie) As ActionResult
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
' Add to database
Try
_db.AddToMovieSet(movieToCreate)
_db.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
El marco de ASP.NET MVC crea la instancia de la película que se pasa a la acción Create() mediante un enlazador de modelos (DefaultModelBinder). El enlazador de modelos es responsable de crear una instancia del objeto Movie enlazando los campos de formulario HTML a una instancia del objeto Movie.
DefaultModelBinder detecta si una clase implementa o no la interfaz IDataErrorInfo. Si una clase implementa esta interfaz, el enlazador de modelos invoca al indexador IDataErrorInfo.this para cada propiedad de la clase. Si el indexador devuelve un mensaje de error, el enlazador de modelos agrega este mensaje de error al estado del modelo de forma automática.
DefaultModelBinder también comprueba la propiedad IDataErrorInfo.Error. Esta propiedad está pensada para representar errores de validación no específicos de propiedades asociados a la clase. Por ejemplo, es posible que quiera aplicar una regla de validación que dependa de los valores de varias propiedades de la clase Movie. En ese caso, devolvería un error de validación desde la propiedad Error.
La clase Movie actualizada de la lista 4 implementa la interfaz IDataErrorInfo.
Lista 4: Models\Movie.vb (implementa IDataErrorInfo)
Imports System.ComponentModel
Partial Public Class Movie
Implements IDataErrorInfo
Private _errors As New Dictionary(Of String, String)()
Private Sub OnTitleChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Title", "Title is required.")
End If
End Sub
Private Sub OnDirectorChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Director", "Director is required.")
End If
End Sub
#Region "IDataErrorInfo Members"
Public ReadOnly Property [Error]() As String Implements IDataErrorInfo.Error
Get
Return String.Empty
End Get
End Property
Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements IDataErrorInfo.Item
Get
If _errors.ContainsKey(columnName) Then
Return _errors(columnName)
End If
Return String.Empty
End Get
End Property
#End Region
End Class
En la lista 4, la propiedad indexer comprueba la colección _errors para ver si contiene una clave que corresponda al nombre de propiedad que se pasa al indexador. Si no hay ningún error de validación asociado a la propiedad, se devuelve una cadena vacía.
No es necesario modificar de ninguna forma el controlador Home para utilizar la clase Movie modificada. La página que aparece en la figura 3 muestra lo que sucede cuando no se especifica ningún valor para los campos de formulario Title o Director.
Figura 03: Formulario con valores que faltan (Haga clic para ver la imagen a tamaño completo)
Observe que el valor DateReleased se valida automáticamente. Como la propiedad DateReleased no acepta valores NULL, DefaultModelBinder genera un error de validación para esta propiedad automáticamente cuando no tiene un valor. Si desea modificar el mensaje de error de la propiedad DateReleased, debe crear un enlazador de modelos personalizado.
Resumen
En este tutorial, ha aprendido a utilizar la interfaz IDataErrorInfo para generar mensajes de error de validación. En primer lugar, hemos creado una clase Movie parcial que amplía la funcionalidad de la clase Movie parcial generada por Entity Framework. A continuación, hemos agregado lógica de validación a los métodos parciales OnTitleChanging() y OnDirectorChanging() de la clase Movie. Por último, hemos implementado la interfaz IDataErrorInfo para exponer estos mensajes de validación en el marco de ASP.NET MVC.


