Walidacja z użyciem interfejsu IDataErrorInfo (VB)

Autor: Stephen Walther

Stephen Walther pokazuje, jak wyświetlać niestandardowe komunikaty o błędach walidacji przez zaimplementowanie interfejsu IDataErrorInfo w klasie modelu.

Celem tego samouczka jest wyjaśnienie jednego podejścia do przeprowadzania walidacji w aplikacji MVC ASP.NET. Dowiesz się, jak uniemożliwić komuś przesłanie formularza HTML bez podawania wartości wymaganych pól formularza. Z tego samouczka dowiesz się, jak przeprowadzić walidację przy użyciu interfejsu IErrorDataInfo.

Założenia

W tym samouczku użyję bazy danych MoviesDB i tabeli bazy danych Filmy. Ta tabela zawiera następujące kolumny:

Nazwa kolumny Typ danych Zezwalaj na wartości null
Id int Fałsz
Tytuł Nvarchar(100) Fałsz
Dyrektor Nvarchar(100) Fałsz
Data wydania DateTime Fałsz

W tym samouczku do generowania klas modelu bazy danych używam programu Microsoft Entity Framework. Klasa Movie wygenerowana przez platformę Entity Framework jest wyświetlana na rysunku 1.

Jednostka Movie

Rysunek 01. Jednostka Movie (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Aby dowiedzieć się więcej na temat używania programu Entity Framework do generowania klas modelu bazy danych, zobacz mój samouczek zatytułowany Tworzenie klas modeli za pomocą platformy Entity Framework.

Klasa kontrolera

Używamy kontrolera Home do wyświetlania listy filmów i tworzenia nowych filmów. Kod dla tej klasy znajduje się na liście 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

Klasa kontrolera Home w liście 1 zawiera dwie akcje Create(). Pierwsza akcja wyświetla formularz HTML do tworzenia nowego filmu. Druga akcja Create() wykonuje rzeczywiste wstawianie nowego filmu do bazy danych. Druga akcja Create() jest wywoływana po przesłaniu formularza wyświetlanego przez pierwszą akcję Create() do serwera.

Zwróć uwagę, że druga akcja Create() zawiera następujące wiersze kodu:

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

Właściwość IsValid zwraca wartość false, gdy wystąpi błąd walidacji. W takim przypadku widok Utwórz zawierający formularz HTML do tworzenia filmu jest odtwarzany ponownie.

Tworzenie klasy częściowej

Klasa Movie jest generowana przez program Entity Framework. Kod klasy Movie można zobaczyć po rozwinięciu pliku MoviesDBModel.edmx w oknie Eksplorator rozwiązań i otwarciu pliku MoviesDBModel.Projektant. plik vb w Edytorze kodu (zobacz Rysunek 2).

Kod jednostki Movie

Rysunek 02. Kod jednostki Film (kliknij, aby wyświetlić obraz pełnowymiarowy)

Klasa Movie jest klasą częściową. Oznacza to, że możemy dodać kolejną klasę częściową o tej samej nazwie, aby rozszerzyć funkcjonalność klasy Movie. Dodamy logikę walidacji do nowej klasy częściowej.

Dodaj klasę w liście 2 do folderu Models.

Lista 2 — Models\Movie.vb

Public Partial Class Movie

End Class

Zwróć uwagę, że klasa na liście 2 zawiera modyfikator częściowy . Wszystkie metody lub właściwości dodane do tej klasy stają się częścią klasy Movie wygenerowanej przez platformę Entity Framework.

Dodawanie metod częściowych OnChanging i OnChanged

Gdy platforma Entity Framework wygeneruje klasę jednostki, program Entity Framework automatycznie dodaje metody częściowe do klasy. Platforma Entity Framework generuje metody częściowe OnChanging i OnChanged, które odpowiadają każdej właściwości klasy.

W przypadku klasy Movie platforma Entity Framework tworzy następujące metody:

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

Metoda OnChanging jest wywoływana bezpośrednio przed zmianą odpowiedniej właściwości. Metoda OnChanged jest wywoływana bezpośrednio po zmianie właściwości.

Możesz skorzystać z tych częściowych metod, aby dodać logikę walidacji do klasy Movie. Aktualizacja klasy Movie na liście 3 sprawdza, czy właściwości Tytuł i Reżyser nie mają przypisanych wartości brakujących.

Uwaga

Metoda częściowa to metoda zdefiniowana w klasie, której nie trzeba implementować. Jeśli nie zaimplementujesz metody częściowej, kompilator usunie sygnaturę metody i wszystkie wywołania metody, aby nie było żadnych kosztów czasu wykonywania skojarzonych z metodą częściową. W edytorze Visual Studio Code można dodać metodę częściową, wpisując słowo kluczowe częściowo, a następnie spację, aby wyświetlić listę częściowych do zaimplementowania.

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

Jeśli na przykład próbujesz przypisać pusty ciąg do właściwości Title, do słownika o nazwie _errors zostanie przypisany komunikat o błędzie.

W tym momencie nic się nie dzieje po przypisaniu pustego ciągu do właściwości Title i do pola prywatnego _errors jest dodawany błąd. Musimy zaimplementować interfejs IDataErrorInfo, aby uwidocznić te błędy weryfikacji na platformie ASP.NET MVC.

Implementowanie interfejsu IDataErrorInfo

Interfejs IDataErrorInfo jest częścią programu .NET Framework od pierwszej wersji. Ten interfejs jest bardzo prostym interfejsem:

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

Jeśli klasa implementuje interfejs IDataErrorInfo, platforma ASP.NET MVC użyje tego interfejsu podczas tworzenia wystąpienia klasy. Na przykład akcja Create() kontrolera głównego akceptuje wystąpienie klasy 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

Struktura ASP.NET MVC tworzy wystąpienie elementu Movie przekazane do akcji Create() przy użyciu powiązania modelu (DefaultModelBinder). Powiązanie modelu jest odpowiedzialne za utworzenie wystąpienia obiektu Movie przez powiązanie pól formularza HTML z wystąpieniem obiektu Movie.

Parametr DefaultModelBinder wykrywa, czy klasa implementuje interfejs IDataErrorInfo. Jeśli klasa implementuje ten interfejs, binder modelu wywołuje indeksator IDataErrorInfo.this dla każdej właściwości klasy. Jeśli indeksator zwraca komunikat o błędzie, powiązanie modelu automatycznie dodaje ten komunikat o błędzie do stanu modelu.

Właściwość DefaultModelBinder sprawdza również właściwość IDataErrorInfo.Error. Ta właściwość jest przeznaczona do reprezentowania błędów weryfikacji specyficznych dla właściwości skojarzonych z klasą. Na przykład można wymusić regułę weryfikacji, która zależy od wartości wielu właściwości klasy Movie. W takim przypadku zostanie zwrócony błąd weryfikacji z właściwości Error.

Zaktualizowana klasa Movie na liście 4 implementuje interfejs IDataErrorInfo.

Lista 4 — Models\Movie.vb (implementuje 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 liście 4 właściwość indeksatora sprawdza kolekcję _errors, aby sprawdzić, czy zawiera klucz odpowiadający nazwie właściwości przekazanej do indeksatora. Jeśli nie ma błędu sprawdzania poprawności skojarzonego z właściwością, zwracany jest pusty ciąg.

Nie musisz modyfikować kontrolera Home w żaden sposób, aby używać zmodyfikowanej klasy Movie. Strona wyświetlana na rysunku 3 ilustruje, co się stanie, gdy dla pól formularza Tytuł lub Dyrektor nie zostanie wprowadzona żadna wartość.

Automatyczne tworzenie metod akcji

Rysunek 03. Formularz z brakującymi wartościami (kliknij, aby wyświetlić obraz pełnowymiarowy)

Zwróć uwagę, że wartość DateReleased jest sprawdzana automatycznie. Ponieważ właściwość DateReleased nie akceptuje wartości NULL, właściwość DefaultModelBinder generuje błąd walidacji dla tej właściwości automatycznie, gdy nie ma wartości. Jeśli chcesz zmodyfikować komunikat o błędzie dla właściwości DateReleased, musisz utworzyć niestandardowy binder modelu.

Podsumowanie

W tym samouczku przedstawiono sposób używania interfejsu IDataErrorInfo do generowania komunikatów o błędach walidacji. Najpierw utworzyliśmy częściową klasę Movie, która rozszerza funkcjonalność częściowej klasy Movie wygenerowanej przez platformę Entity Framework. Następnie dodaliśmy logikę walidacji do metod częściowych Klasy Movie OnTitleChanging() i OnDirectorChanging(). Na koniec zaimplementowaliśmy interfejs IDataErrorInfo w celu uwidocznienia tych komunikatów weryfikacji na platformie ASP.NET MVC.