Dodawanie logiki weryfikacji do modelu filmowego
Uwaga
Zaktualizowana wersja tego samouczka jest dostępna tutaj, która używa ASP.NET MVC 5 i Visual Studio 2013. Jest ona bezpieczniejsza, znacznie łatwiejsza do naśladowania i demonstruje więcej funkcji.
W tej sekcji dodasz logikę walidacji do Movie
modelu i upewnisz się, że reguły weryfikacji są wymuszane za każdym razem, gdy użytkownik próbuje utworzyć lub edytować film przy użyciu aplikacji.
Utrzymywanie suchych rzeczy
Jeden z podstawowych zestawów projektowych ASP.NET MVC to DRY ("Nie powtarzaj siebie"). ASP.NET MVC zachęca do określania funkcjonalności lub zachowania tylko raz, a następnie ich odzwierciedlenia wszędzie w aplikacji. Zmniejsza to ilość kodu potrzebnego do pisania i sprawia, że kod jest mniej podatny na błędy i ułatwia konserwację.
Obsługa walidacji zapewniana przez ASP.NET MVC i Entity Framework Code First to doskonały przykład akcji zasady DRY. Reguły weryfikacji można deklaratywne określić w jednym miejscu (w klasie modelu), a reguły są wymuszane wszędzie w aplikacji.
Przyjrzyjmy się, jak można skorzystać z tej obsługi walidacji w aplikacji filmowej.
Dodawanie reguł walidacji do modelu filmowego
Zaczniesz od dodania logiki weryfikacji do Movie
klasy.
Otwórz plik Movie.cs . Dodaj instrukcję using
w górnej części pliku, który odwołuje się do System.ComponentModel.DataAnnotations
przestrzeni nazw:
using System.ComponentModel.DataAnnotations;
Zwróć uwagę, że przestrzeń nazw nie zawiera System.Web
elementu . Funkcja DataAnnotations udostępnia wbudowany zestaw atrybutów weryfikacji, które można deklaratywnie zastosować do dowolnej klasy lub właściwości.
Teraz zaktualizuj klasę Movie
, aby korzystać z wbudowanych Required
atrybutów , StringLength
i Range
walidacji. Użyj następującego kodu jako przykładu miejsca zastosowania atrybutów.
public class Movie {
public int ID { get; set; }
[Required]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
}
Uruchom aplikację i ponownie zostanie wyświetlony następujący błąd czasu wykonywania:
Model tworzący kopię zapasową kontekstu "MovieDBContext" zmienił się od czasu utworzenia bazy danych. Rozważ użycie Migracje Code First do zaktualizowania bazy danych (https://go.microsoft.com/fwlink/?LinkId=238269).
Użyjemy migracji do zaktualizowania schematu. Skompiluj rozwiązanie, a następnie otwórz okno Konsola menedżera pakietów i wprowadź następujące polecenia:
add-migration AddDataAnnotationsMig
update-database
Po zakończeniu tego polecenia program Visual Studio otwiera plik klasy definiujący nową DbMigration
klasę pochodną o określonej nazwie (AddDataAnnotationsMig), a w Up
metodzie można zobaczyć kod, który aktualizuje ograniczenia schematu. Pola Title
i Genre
nie są już dopuszczające wartości null (oznacza to, że należy wprowadzić wartość), a Rating
pole ma maksymalną długość 5.
Atrybuty weryfikacji określają zachowanie, do którego mają być wymuszane właściwości modelu. Atrybut wskazuje, że właściwość musi mieć wartość. W Required
tym przykładzie film musi mieć wartości właściwości Title
, ReleaseDate
, Genre
i Price
, aby być prawidłowe. Atrybut Range
ogranicza wartość do określonego zakresu. Atrybut StringLength
umożliwia ustawienie maksymalnej długości właściwości ciągu i opcjonalnie jej minimalnej długości. Typy wewnętrzne (takie jak decimal, int, float, DateTime
) są domyślnie wymagane i nie wymagają atrybutu Required
.
Code First gwarantuje, że reguły weryfikacji określone w klasie modelu są wymuszane przed zapisaniem zmian w bazie danych przez aplikację. Na przykład poniższy kod zgłosi wyjątek po SaveChanges
wywołaniu metody, ponieważ brakuje kilku wymaganych Movie
wartości właściwości, a cena jest równa zero (która jest poza prawidłowym zakresem).
MovieDBContext db = new MovieDBContext();
Movie movie = new Movie();
movie.Title = "Gone with the Wind";
movie.Price = 0.0M;
db.Movies.Add(movie);
db.SaveChanges(); // <= Will throw server side validation exception
Automatyczne wymuszanie reguł weryfikacji przez .NET Framework pomaga zwiększyć niezawodność aplikacji. Gwarantuje to również, że nie można zapomnieć o zweryfikowaniu czegoś i przypadkowo zezwolić na nieprawidłowe dane w bazie danych.
Oto pełna lista kodu dla zaktualizowanego pliku Movie.cs :
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Models {
public class Movie {
public int ID { get; set; }
[Required]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
}
public class MovieDBContext : DbContext {
public DbSet<Movie> Movies { get; set; }
}
}
Interfejs użytkownika błędu walidacji w usłudze ASP.NET MVC
Uruchom ponownie aplikację i przejdź do adresu URL /Movies .
Kliknij link Utwórz nowy , aby dodać nowy film. Wypełnij formularz nieprawidłowymi wartościami, a następnie kliknij przycisk Utwórz .
Uwaga
aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego, należy uwzględnić globalize.js i określone kultury/globalize.cultures.js plików(z https://github.com/jquery/globalize ) i JavaScript do użycia Globalize.parseFloat
. Poniższy kod przedstawia modyfikacje pliku Views\Movies\Edit.cshtml do pracy z kulturą "fr-FR":
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/globalize.js"></script>
<script src="~/Scripts/globalize.culture.fr-FR.js"></script>
<script>
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture('fr-FR');
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Use the Globalization plugin to parse the value
var val = $.global.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
</script>
}
Zwróć uwagę, że formularz automatycznie używał koloru czerwonego obramowania w celu wyróżnienia pól tekstowych zawierających nieprawidłowe dane i emitował odpowiedni komunikat o błędzie walidacji obok każdego z nich. Błędy są wymuszane zarówno po stronie klienta (przy użyciu języka JavaScript i jQuery) jak i po stronie serwera (w przypadku wyłączenia języka JavaScript przez użytkownika).
Prawdziwą korzyścią jest to, że nie trzeba zmieniać pojedynczego wiersza kodu w MoviesController
klasie ani w widoku Create.cshtml w celu włączenia tego interfejsu użytkownika weryfikacji. Kontroler i widoki utworzone wcześniej w tym samouczku automatycznie odebrały reguły sprawdzania poprawności określone przy użyciu atrybutów weryfikacji we właściwościach Movie
klasy modelu.
Być może zauważysz, że właściwości Title
i Genre
, wymagany atrybut nie jest wymuszany, dopóki formularz nie zostanie przesłany (naciśnij przycisk Utwórz ) lub wprowadź tekst w polu wejściowym i go usunął. W przypadku pola, które jest początkowo puste (takie jak pola w widoku Tworzenie) i które ma tylko wymagany atrybut i nie ma innych atrybutów weryfikacji, możesz wykonać następujące czynności, aby wyzwolić walidację:
- Karta w polu.
- Wprowadź jakiś tekst.
- Wyprzedaj kartę.
- Karta z powrotem do pola.
- Usuń tekst.
- Wyprzedaj kartę.
Powyższa sekwencja wyzwoli wymaganą walidację bez naciśnięcia przycisku przesyłania. Po prostu naciśnięcie przycisku przesyłania bez wprowadzania żadnego z pól spowoduje wyzwolenie weryfikacji po stronie klienta. Dane formularza nie są wysyłane do serwera, dopóki nie wystąpią żadne błędy weryfikacji po stronie klienta. Można to przetestować, umieszczając punkt przerwania w metodzie HTTP Post lub za pomocą narzędzia fiddler lub narzędzi deweloperskich IE 9 F12.
Jak występuje walidacja w metodzie Create View and Create Action
Możesz się zastanawiać, w jaki sposób interfejs użytkownika weryfikacji został wygenerowany bez żadnych aktualizacji kodu w kontrolerze lub widokach. Następna lista pokazuje, jak Create
wyglądają metody w MovieController
klasie. Nie zmieniają się one w sposób, w jaki zostały utworzone wcześniej w tym samouczku.
//
// GET: /Movies/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Movies/Create
[HttpPost]
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
Pierwsza metoda akcji (HTTP GET) Create
wyświetla początkowy formularz Create. Druga wersja ([HttpPost]
) obsługuje wpis formularza. Create
Druga metoda (wersjaHttpPost
) wywołuje, ModelState.IsValid
aby sprawdzić, czy film ma jakiekolwiek błędy walidacji. Wywołanie tej metody ocenia wszystkie atrybuty weryfikacji, które zostały zastosowane do obiektu. Jeśli obiekt ma błędy walidacji, Create
metoda ponownie wyświetla formularz. Jeśli nie ma żadnych błędów, metoda zapisuje nowy film w bazie danych. W naszym przykładzie filmu używanym formularz nie jest publikowany na serwerze po wykryciu błędów weryfikacji po stronie klienta; drugaCreate
metoda nigdy nie jest wywoływana. Jeśli wyłączysz język JavaScript w przeglądarce, walidacja klienta jest wyłączona i wywołania ModelState.IsValid
metody HTTP POST Create
w celu sprawdzenia, czy film ma jakiekolwiek błędy weryfikacji.
Można ustawić punkt przerwania w metodzie HttpPost Create
i sprawdzić, czy metoda nigdy nie jest wywoływana, walidacja po stronie klienta nie będzie przesyłać danych formularza po wykryciu błędów weryfikacji. Jeśli wyłączysz język JavaScript w przeglądarce, prześlij formularz z błędami, punkt przerwania zostanie trafiony. Nadal uzyskujesz pełną walidację bez języka JavaScript. Na poniższej ilustracji pokazano, jak wyłączyć język JavaScript w programie Internet Explorer.
Na poniższej ilustracji pokazano, jak wyłączyć język JavaScript w przeglądarce FireFox.
Na poniższej ilustracji pokazano, jak wyłączyć język JavaScript za pomocą przeglądarki Chrome.
Poniżej znajduje się szablon widoku Create.cshtml , który został utworzony wcześniej w samouczku. Jest on używany przez metody akcji pokazane powyżej, aby wyświetlić formularz początkowy i odtworzyć go w przypadku błędu.
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Genre)
@Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Rating)
@Html.ValidationMessageFor(model => model.Rating)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Zwróć uwagę, jak kod używa Html.EditorFor
pomocnika do wyprowadzania <input>
elementu dla każdej Movie
właściwości. Obok tego pomocnika jest wywołanie Html.ValidationMessageFor
metody pomocnika. Te dwie metody pomocnicze działają z obiektem modelu przekazywanym przez kontroler do widoku (w tym przypadku obiektem Movie
). Automatycznie wyszukują atrybuty weryfikacji określone w modelu i wyświetlają odpowiednio komunikaty o błędach.
To, co jest naprawdę miłe w tym podejściu, to to, że ani kontroler, ani szablon Tworzenia widoku nie wie nic o rzeczywistych regułach weryfikacji, które są wymuszane, ani o wyświetlanych konkretnych komunikatach o błędach. Reguły walidacji i ciągi błędów są określone tylko w Movie
klasie. Te same reguły sprawdzania poprawności są automatycznie stosowane do widoku Edytuj i innych szablonów widoków, które można utworzyć, aby edytować model.
Jeśli chcesz później zmienić logikę weryfikacji, możesz to zrobić w dokładnie jednym miejscu, dodając atrybuty weryfikacji do modelu (w tym przykładzie movie
klasa). Nie trzeba martwić się o niespójność różnych części aplikacji ze sposobem wymuszania reguł — wszystkie logiki weryfikacji będą definiowane w jednym miejscu i używane wszędzie. Dzięki temu kod jest bardzo czysty i ułatwia konserwację i rozwijanie. Oznacza to, że będziesz w pełni honorować zasadę DRY.
Dodawanie formatowania do modelu filmowego
Otwórz plik Movie.cs i sprawdź klasę Movie
. System.ComponentModel.DataAnnotations
Przestrzeń nazw udostępnia atrybuty formatowania oprócz wbudowanego zestawu atrybutów weryfikacji. Do daty wydania i pól cen zastosowaliśmy DataType
już wartość wyliczenia. Poniższy kod przedstawia ReleaseDate
właściwości i Price
z odpowiednim DisplayFormat
atrybutem.
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[DataType(DataType.Currency)]
public decimal Price { get; set; }
Atrybuty nie są atrybutami weryfikacji. Są DataType
one używane do określania aparatu wyświetlania sposobu renderowania kodu HTML. W powyższym DataType.Date
przykładzie atrybut wyświetla daty filmu tylko jako daty bez godziny. Na przykład następujące DataType
atrybuty nie weryfikują formatu danych:
[DataType(DataType.EmailAddress)]
[DataType(DataType.PhoneNumber)]
[DataType(DataType.Url)]
Atrybuty wymienione powyżej zawierają tylko wskazówki dla aparatu wyświetlania, aby sformatować dane (i podać atrybuty, takie jak <> adres URL i <href="mailto:EmailAddress.com"> dla wiadomości e-mail. Możesz użyć atrybutu RegularExpression , aby zweryfikować format danych.
Alternatywne podejście do używania DataType
atrybutów można jawnie ustawić DataFormatString
wartość. Poniższy kod przedstawia właściwość daty wydania z ciągiem formatu daty (czyli "d"). Użyjesz tego polecenia, aby określić, że nie chcesz używać godziny w ramach daty wydania.
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime ReleaseDate { get; set; }
Poniżej przedstawiono kompletną Movie
klasę.
public class Movie {
public int ID { get; set; }
[Required]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
}
Uruchom aplikację i przejdź do Movies
kontrolera. Data wydania i cena są ładnie sformatowane. Na poniższej ilustracji przedstawiono datę i cenę wydania przy użyciu wartości "fr-FR" jako kultury.
Na poniższej ilustracji przedstawiono te same dane wyświetlane z kulturą domyślną (angielski stany USA).
W następnej części serii przejrzymy aplikację i wprowadzimy pewne ulepszenia automatycznie wygenerowane Details
i Delete
metody.
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla