Compartilhar via


Validação com a interface IDataErrorInfo (VB)

por Stephen Walther

Stephen Walther mostra como exibir mensagens de erro de validação personalizadas implementando a interface IDataErrorInfo em uma classe de modelo.

O objetivo deste tutorial é explicar uma abordagem para executar a validação em um aplicativo MVC ASP.NET. Você aprenderá a impedir que alguém envie um formulário HTML sem fornecer valores para os campos de formulário necessários. Neste tutorial, você aprenderá a executar a validação usando a interface IErrorDataInfo.

Suposições

Neste tutorial, usarei o banco de dados MoviesDB e a tabela de banco de dados Filmes. Essa tabela tem as seguintes colunas:

Nome da Coluna Tipo de Dados Permitir Nulos
ID int Falso
Title Nvarchar(100) Falso
Diretor Nvarchar(100) Falso
DateReleased Datetime Falso

Neste tutorial, uso o Microsoft Entity Framework para gerar minhas classes de modelo de banco de dados. A classe Movie gerada pelo Entity Framework é exibida na Figura 1.

A entidade Movie

Figura 01: a entidade Movie (clique para exibir a imagem em tamanho real)

Observação

Para saber mais sobre como usar o Entity Framework para gerar suas classes de modelo de banco de dados, confira meu tutorial intitulado Criando classes de modelo com o Entity Framework.

A classe Controller

Usamos o controlador Home para listar filmes e criar novos filmes. O código dessa classe está contido na Listagem 1.

Listagem 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

A classe de controlador Home na Listagem 1 contém duas ações Create(). A primeira ação exibe o formulário HTML para criar um novo filme. A segunda ação Create() executa a inserção real do novo filme no banco de dados. A segunda ação Create() é invocada quando o formulário exibido pela primeira ação Create() é enviado ao servidor.

Observe que a segunda ação Create() contém as seguintes linhas de código:

' Validate
If (Not ModelState.IsValid) Then
Return View()
End If

A propriedade IsValid retorna false quando há um erro de validação. Nesse caso, o modo de exibição Criar que contém o formulário HTML para criar um filme é reproduzido novamente.

Criando uma classe parcial

A classe Movie é gerada pelo Entity Framework. Você poderá ver o código da classe Movie se expandir o arquivo MoviesDBModel.edmx na janela Gerenciador de Soluções e abrir o MoviesDBModel.Designer. arquivo vb no Editor de Código (consulte a Figura 2).

O código para a entidade Movie

Figura 02: o código da entidade Movie (Clique para exibir a imagem em tamanho real)

A classe Movie é parcial. Isso significa que podemos adicionar outra classe parcial com o mesmo nome para estender a funcionalidade da classe Movie. Adicionaremos nossa lógica de validação à nova classe parcial.

Adicione a classe na Listagem 2 à pasta Modelos.

Listagem 2 – Models\Movie.vb

Public Partial Class Movie

End Class

Observe que a classe na Listagem 2 inclui o modificador parcial . Todos os métodos ou propriedades que você adicionar a essa classe se tornam parte da classe Movie gerada pelo Entity Framework.

Adicionando métodos parciais OnChanging e OnChanged

Quando o Entity Framework gera uma classe de entidade, o Entity Framework adiciona métodos parciais à classe automaticamente. O Entity Framework gera métodos parciais OnChanging e OnChanged que correspondem a cada propriedade da classe .

No caso da classe Movie, o Entity Framework cria os seguintes métodos:

  • OnIdChanging
  • OnIdChanged
  • OnTitleChanging
  • OnTitleChanged
  • OnDirectorChanging
  • OnDirectorChanged
  • OnDateReleasedChanging
  • OnDateReleasedChanged

O método OnChanging é chamado logo antes da propriedade correspondente ser alterada. O método OnChanged é chamado logo após a propriedade ser alterada.

Você pode aproveitar esses métodos parciais para adicionar a lógica de validação à classe Movie. A classe update Movie na Listagem 3 verifica se as propriedades Title e Director recebem valores não vazios.

Observação

Um método parcial é um método definido em uma classe que você não precisa implementar. Se você não implementar um método parcial, o compilador removerá a assinatura do método e todas as chamadas para o método para que não haja custos de tempo de execução associados ao método parcial. No Editor de Visual Studio Code, você pode adicionar um método parcial digitando o palavra-chave parcial seguido por um espaço para exibir uma lista de parciais a serem implementadas.

Listagem 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 exemplo, se você tentar atribuir uma cadeia de caracteres vazia à propriedade Title, uma mensagem de erro será atribuída a um Dicionário chamado _errors.

Neste ponto, nada realmente acontece quando você atribui uma cadeia de caracteres vazia à propriedade Title e um erro é adicionado ao campo de _errors privado. Precisamos implementar a interface IDataErrorInfo para expor esses erros de validação à estrutura ASP.NET MVC.

Implementando a interface IDataErrorInfo

A interface IDataErrorInfo faz parte do .NET Framework desde a primeira versão. Essa interface é uma interface muito simples:

Public Interface IDataErrorInfo
  Default ReadOnly Property Item(ByVal columnName As String) As String
  ReadOnly Property [Error]() As String
End Interface

Se uma classe implementar a interface IDataErrorInfo, a estrutura ASP.NET MVC usará essa interface ao criar uma instância da classe . Por exemplo, a ação Criar() do controlador Inicial aceita uma instância da classe 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

A estrutura ASP.NET MVC cria a instância do Filme passada para a ação Create() usando um associador de modelo (o DefaultModelBinder). O associador de modelo é responsável por criar uma instância do objeto Movie associando os campos de formulário HTML a uma instância do objeto Movie.

O DefaultModelBinder detecta se uma classe implementa ou não a interface IDataErrorInfo. Se uma classe implementar essa interface, o associador de modelo invocará o IDataErrorInfo.this indexer para cada propriedade da classe. Se o indexador retornar uma mensagem de erro, o associador de modelo adicionará essa mensagem de erro ao estado do modelo automaticamente.

O DefaultModelBinder também verifica a propriedade IDataErrorInfo.Error. Essa propriedade destina-se a representar erros de validação não específicos de propriedade associados à classe . Por exemplo, talvez você queira impor uma regra de validação que dependa dos valores de várias propriedades da classe Movie. Nesse caso, você retornaria um erro de validação da propriedade Error.

A classe Movie atualizada na Listagem 4 implementa a interface IDataErrorInfo.

Listagem 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

Na Listagem 4, a propriedade do indexador verifica a coleção _errors para ver se ela contém uma chave que corresponde ao nome da propriedade passada para o indexador. Se não houver nenhum erro de validação associado à propriedade, uma cadeia de caracteres vazia será retornada.

Você não precisa modificar o controlador Home de forma alguma para usar a classe Movie modificada. A página exibida na Figura 3 ilustra o que acontece quando nenhum valor é inserido para os campos de formulário Título ou Diretor.

Criando métodos de ação automaticamente

Figura 03: um formulário com valores ausentes (Clique para exibir a imagem em tamanho real)

Observe que o valor DateReleased é validado automaticamente. Como a propriedade DateReleased não aceita valores NULL, o DefaultModelBinder gera um erro de validação para essa propriedade automaticamente quando não tem um valor. Se você quiser modificar a mensagem de erro para a propriedade DateReleased, precisará criar um associador de modelo personalizado.

Resumo

Neste tutorial, você aprendeu a usar a interface IDataErrorInfo para gerar mensagens de erro de validação. Primeiro, criamos uma classe Movie parcial que estende a funcionalidade da classe Movie parcial gerada pelo Entity Framework. Em seguida, adicionamos a lógica de validação aos métodos parciais OnTitleChanging() e OnDirectorChanging(). Por fim, implementamos a interface IDataErrorInfo para expor essas mensagens de validação à estrutura ASP.NET MVC.