Compartir a través de


Validación de la interfaz IDataErrorInfo (VB)

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.

The Movie entity

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).

The code for the Movie entity

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.

Creating action methods automatically

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.