Condividi tramite


Convalida con l'interfaccia IDataErrorInfo (VB)

di Stephen Walther

Stephen Walther illustra come visualizzare messaggi di errore di convalida personalizzati implementando l'interfaccia IDataErrorInfo in una classe modello.

L'obiettivo di questa esercitazione è spiegare un approccio per eseguire la convalida in un'applicazione MVC ASP.NET. Si apprenderà come impedire a un utente di inviare un modulo HTML senza fornire valori per i campi del modulo obbligatori. Questa esercitazione descrive come eseguire la convalida usando l'interfaccia IErrorDataInfo.

Presupposti

In questa esercitazione si userà il database MoviesDB e la tabella di database Movies. Questa tabella contiene le colonne seguenti:

Nome colonna Tipo di dati Consenti valori NULL
ID Int Falso
Titolo Nvarchar (100) Falso
Responsabile Nvarchar (100) Falso
DateReleased Datetime Falso

In questa esercitazione viene usato Microsoft Entity Framework per generare le classi del modello di database. La classe Movie generata da Entity Framework viene visualizzata nella figura 1.

Entità Movie

Figura 01: Entità movie(Fare clic per visualizzare l'immagine full-size)

Nota

Per altre informazioni sull'uso di Entity Framework per generare le classi del modello di database, vedere l'esercitazione relativa alla creazione di classi di modelli con Entity Framework.

Classe Controller

Usiamo il controller Home per elencare i film e creare nuovi film. Il codice per questa classe è contenuto nell'elenco 1.

Elenco 1 - Controller\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 classe controller Home in List 1 contiene due azioni Create(). La prima azione visualizza il modulo HTML per la creazione di un nuovo filmato. La seconda azione Create() esegue l'inserimento effettivo del nuovo filmato nel database. La seconda azione Create() viene richiamata quando il modulo visualizzato dalla prima azione Create() viene inviata al server.

Si noti che la seconda azione Create() contiene le righe di codice seguenti:

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

La proprietà IsValid restituisce false quando si verifica un errore di convalida. In tal caso, la visualizzazione Crea che contiene il modulo HTML per la creazione di un filmato viene ricreata.

Creazione di una classe parziale

La classe Movie viene generata da Entity Framework. È possibile visualizzare il codice per la classe Movie se si espande il file MoviesDBModel.edmx nella finestra Esplora soluzioni e aprire MoviesDBModel.Designer. file vb nell'editor di codice (vedere la figura 2).

Codice per l'entità Movie

Figura 02: Il codice per l'entità Movie(Fare clic per visualizzare l'immagine full-size)

La classe Movie è una classe parziale. Ciò significa che è possibile aggiungere un'altra classe parziale con lo stesso nome per estendere la funzionalità della classe Movie. Verrà aggiunta la logica di convalida alla nuova classe parziale.

Aggiungere la classe in List 2 alla cartella Models.

Elenco 2 - Modelli\Movie.vb

Public Partial Class Movie

End Class

Si noti che la classe in List 2 include il modificatore parziale . Tutti i metodi o le proprietà aggiunti a questa classe diventano parte della classe Movie generata da Entity Framework.

Aggiunta di metodi parziali OnChanging e OnChanged

Quando Entity Framework genera una classe di entità, Entity Framework aggiunge automaticamente metodi parziali alla classe. Entity Framework genera metodi parziali OnChanging e OnChanged che corrispondono a ogni proprietà della classe.

Nel caso della classe Movie, Entity Framework crea i metodi seguenti:

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

Il metodo OnChanging viene chiamato subito prima della modifica della proprietà corrispondente. Il metodo OnChanged viene chiamato subito dopo la modifica della proprietà.

È possibile sfruttare questi metodi parziali per aggiungere la logica di convalida alla classe Movie. La classe Update Movie in List 3 verifica che le proprietà Title e Director siano assegnate valori non dispendiosi.

Nota

Un metodo parziale è un metodo definito in una classe che non è necessaria per implementare. Se non si implementa un metodo parziale, il compilatore rimuove la firma del metodo e tutte le chiamate al metodo in modo che non siano presenti costi di run-time associati al metodo parziale. Nell'editor di Visual Studio Code è possibile aggiungere un metodo parziale digitando la parola chiave parziale seguita da uno spazio per visualizzare un elenco di parziali da implementare.

Elenco 3 - Modelli\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

Ad esempio, se si tenta di assegnare una stringa vuota alla proprietà Title, viene assegnato un messaggio di errore a un dizionario denominato _errors.

A questo punto, non accade nulla quando si assegna una stringa vuota alla proprietà Title e viene aggiunto un errore al campo _errors privato. È necessario implementare l'interfaccia IDataErrorInfo per esporre questi errori di convalida al framework MVC ASP.NET.

Implementazione dell'interfaccia IDataErrorInfo

L'interfaccia IDataErrorInfo fa parte di .NET Framework dalla prima versione. Questa interfaccia è un'interfaccia molto semplice:

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

Se una classe implementa l'interfaccia IDataErrorInfo, il framework ASP.NET MVC userà questa interfaccia durante la creazione di un'istanza della classe. Ad esempio, l'azione Create() del controller Home accetta un'istanza della 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

Il framework ASP.NET MVC crea l'istanza del filmato passata all'azione Create() usando un binding del modello (DefaultModelBinder). Il bindinger del modello è responsabile della creazione di un'istanza dell'oggetto Movie associando i campi del modulo HTML a un'istanza dell'oggetto Movie.

DefaultModelBinder rileva se una classe implementa l'interfaccia IDataErrorInfo. Se una classe implementa questa interfaccia, il bindinger del modello richiama l'indicizzatore IDataErrorInfo.this per ogni proprietà della classe. Se l'indicizzatore restituisce un messaggio di errore, il binder del modello aggiunge automaticamente questo messaggio di errore allo stato del modello.

DefaultModelBinder controlla anche la proprietà IDataErrorInfo.Error. Questa proprietà è destinata a rappresentare errori di convalida specifici della proprietà associati alla classe. Ad esempio, è possibile applicare una regola di convalida che dipende dai valori di più proprietà della classe Movie. In tal caso, verrà restituito un errore di convalida dalla proprietà Error.

La classe Movie aggiornata in List 4 implementa l'interfaccia IDataErrorInfo.

Elenco 4 - Modelli\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

In Elenco 4, la proprietà indicizzatore controlla la raccolta _errors per verificare se contiene una chiave che corrisponde al nome della proprietà passato all'indicizzatore. Se non è presente alcun errore di convalida associato alla proprietà, viene restituita una stringa vuota.

Non è necessario modificare il controller Home in alcun modo per usare la classe Movie modificata. La pagina visualizzata nella figura 3 illustra cosa accade quando non viene immesso alcun valore per i campi del modulo Title o Director.

Creazione automatica di metodi di azione

Figura 03: modulo con valori mancanti (Fare clic per visualizzare l'immagine full-size)

Si noti che il valore DateReleased viene convalidato automaticamente. Poiché la proprietà DateReleased non accetta valori NULL, DefaultModelBinder genera automaticamente un errore di convalida per questa proprietà quando non ha un valore. Se si vuole modificare il messaggio di errore per la proprietà DateReleased, è necessario creare un binding del modello personalizzato.

Riepilogo

In questa esercitazione si è appreso come usare l'interfaccia IDataErrorInfo per generare messaggi di errore di convalida. Prima di tutto, è stata creata una classe Movie parziale che estende la funzionalità della classe Movie parziale generata da Entity Framework. Successivamente, è stata aggiunta la logica di convalida ai metodi parziali OnTitleChanging() e OnDirectorChanging(). Infine, è stata implementata l'interfaccia IDataErrorInfo per esporre questi messaggi di convalida al framework ASP.NET MVC.