Dodawanie walidacji
Uwaga
Zaktualizowana wersja tego samouczka jest dostępna tutaj przy użyciu najnowszej wersji programu Visual Studio. W nowym samouczku użyto ASP.NET Core MVC, co zapewnia wiele ulepszeń w tym samouczku.
W tym samouczku przedstawiono ASP.NET Core MVC z kontrolerami i widokami. Razor Pages to nowa alternatywa w ASP.NET Core, oparty na stronach model programowania, który ułatwia tworzenie internetowego interfejsu użytkownika i bardziej wydajne. Zalecamy wypróbowanie samouczka Razor Pages przed wersją MVC. Samouczek usługi Razor Pages:
- Jest łatwiejsze do naśladowania.
- Obejmuje więcej funkcji.
- Jest preferowanym podejściem do tworzenia nowych aplikacji.
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 . Zwróć uwagę, że System.ComponentModel.DataAnnotations
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. (Zawiera również atrybuty formatowania, takie jak DataType , które ułatwiają formatowanie i nie zapewniają żadnej weryfikacji).
Teraz zaktualizuj klasęMovie
, aby skorzystać z wbudowanych Required
atrybutów , StringLength
, RegularExpression i Range
walidacji. Zastąp klasę Movie
następującymi elementami:
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
[StringLength(5)]
public string Rating { get; set; }
}
Atrybut StringLength
ustawia maksymalną długość ciągu i ustawia to ograniczenie w bazie danych, dlatego schemat bazy danych ulegnie zmianie. Kliknij prawym przyciskiem myszy tabelę Filmy w Eksploratorze serwera i kliknij pozycję Otwórz definicję tabeli:
Na powyższym obrazie widać, że wszystkie pola ciągu są ustawione na NVARCHAR (MAX). 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 DataAnnotations
update-database
Po zakończeniu tego polecenia program Visual Studio otworzy plik klasy definiujący nową DbMigration
klasę pochodną o określonej nazwie (DataAnnotations
), a w Up
metodzie można zobaczyć kod, który aktualizuje ograniczenia schematu:
public override void Up()
{
AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60));
AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false, maxLength: 30));
AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
}
Pole Genre
nie jest już możliwe do wartości null (oznacza to, że należy wprowadzić wartość). Pole Rating
ma maksymalną długość 5 i Title
ma maksymalną długość 60. Minimalna długość 3 na i Title
zakres nie Price
utworzył zmian schematu.
Sprawdź schemat filmu:
Pola ciągu pokazują nowe limity długości i Genre
nie są już sprawdzane jako dopuszczane do wartości null.
Atrybuty weryfikacji określają zachowanie, do którego mają być wymuszane właściwości modelu. Atrybuty Required
i MinimumLength
wskazują, że właściwość musi mieć wartość, ale nic nie uniemożliwia użytkownikowi wprowadzenia białych znaków w celu spełnienia tej weryfikacji. Atrybut RegularExpression służy do ograniczania liczby znaków, które mogą być wprowadzane. W powyższym Genre
Rating
kodzie należy używać tylko liter (białe znaki, cyfry i znaki specjalne są niedozwolone). 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 wartości (takie jak decimal, int, float, DateTime
) są z natury 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 DbEntityValidationException po SaveChanges
wywołaniu metody, ponieważ brakuje kilku wymaganych Movie
wartości właściwości:
MovieDBContext db = new MovieDBContext();
Movie movie = new Movie();
movie.Title = "Gone with the Wind";
db.Movies.Add(movie);
db.SaveChanges(); // <= Will throw server side validation exception
Powyższy kod zgłasza następujący wyjątek:
Walidacja nie powiodła się dla co najmniej jednej jednostki. Aby uzyskać więcej informacji, zobacz właściwość EntityValidationErrors.
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.
Interfejs użytkownika błędu walidacji w usłudze ASP.NET MVC
Uruchom aplikację i przejdź do adresu URL /Movies .
Kliknij link Utwórz nowy , aby dodać nowy film. Wypełnij formularz kilkoma nieprawidłowymi wartościami. Gdy tylko walidacja po stronie klienta jQuery wykryje błąd, zostanie wyświetlony komunikat o błędzie.
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ć globalizowanie NuGet zgodnie z opisem wcześniej w tym samouczku.
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. Przetestuj walidację Edit
przy użyciu metody akcji i zastosowano tę samą walidację.
Dane formularza nie są wysyłane do serwera, dopóki nie wystąpią żadne błędy weryfikacji po stronie klienta. Możesz to sprawdzić, umieszczając punkt przerwania w metodzie HTTP Post przy użyciu narzędzia fiddler lub narzędzi deweloperskich IE 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.
public ActionResult Create()
{
return View();
}
// POST: /Movies/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] 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. Druga Create
metoda ( HttpPost
wersja) sprawdza ModelState.IsValid
, czy film ma jakiekolwiek błędy walidacji. Pobieranie tej właściwości ocenia wszystkie atrybuty weryfikacji, które zostały zastosowane do obiektu. Jeśli obiekt ma błędy walidacji, Create
metoda redisplays formularza. Jeśli nie ma żadnych błędów, metoda zapisuje nowy film w bazie danych. W naszym przykładzie filmu formularz nie jest publikowany na serwerze, gdy występują błędy weryfikacji wykryte po stronie klienta; drugaCreate
metoda nigdy nie jest wywoływana. Jeśli wyłączysz język JavaScript w przeglądarce, walidacja klienta zostanie wyłączona, a metoda HTTP POST Create
sprawdzi ModelState.IsValid
, 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 w przeglądarce 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>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
@*Fields removed for brevity.*@
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
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 naprawdę jest miłe w tym podejściu, to to, że ani kontroler, ani Create
szablon widoku nic nie wie o rzeczywistych regułach weryfikacji, które są wymuszane, lub 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 Edit
widoku i wszelkich 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 .
Używanie atrybutów Typu danych
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 DataType
atrybutem.
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[DataType(DataType.Currency)]
public decimal Price { get; set; }
Atrybuty DataType zawierają tylko wskazówki dla aparatu wyświetlania, aby sformatować dane (i podać atrybuty, takie jak <a>
adres URL i <a href="mailto:EmailAddress.com">
adres e-mail. Możesz użyć atrybutu RegularExpression , aby zweryfikować format danych. Atrybut DataType służy do określania typu danych, który jest bardziej specyficzny niż typ wewnętrzny bazy danych, nie są atrybutami weryfikacji. W tym przypadku chcemy śledzić tylko datę, a nie datę i godzinę. Wyliczenie DataType zawiera wiele typów danych, takich jak Data, Godzina, Liczba telefonów, Waluta, Adres e-mail i inne. Atrybut DataType
może również umożliwić aplikacji automatyczne udostępnianie funkcji specyficznych dla typu. Na przykład mailto:
można utworzyć link dla elementu DataType.EmailAddress, a selektor dat można podać dla elementu DataType.Date w przeglądarkach, które obsługują kod HTML5. Atrybuty DataType emitują atrybuty HTML 5 data- (wymawiane kreski danych), które mogą zrozumieć przeglądarki HTML 5. Atrybuty DataType nie zapewniają żadnej weryfikacji.
DataType.Date
nie określa formatu wyświetlanej daty. Domyślnie pole danych jest wyświetlane zgodnie z domyślnymi formatami na podstawie informacji o kulturze serwera.
Atrybut DisplayFormat
jest używany do jawnego określenia formatu daty:
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
Ustawienie ApplyFormatInEditMode
określa, że określone formatowanie powinno być również stosowane, gdy wartość jest wyświetlana w polu tekstowym do edycji. (Możesz tego nie chcieć w przypadku niektórych pól — na przykład w przypadku wartości waluty możesz nie chcieć symbolu waluty w polu tekstowym do edycji).
Atrybut DisplayFormat można użyć sam w sobie, ale zazwyczaj warto użyć atrybutu DataType . Atrybut DataType
przekazuje semantyka danych w przeciwieństwie do sposobu renderowania ich na ekranie i zapewnia następujące korzyści, których nie otrzymujesz za DisplayFormat
pomocą polecenia :
- Przeglądarka może włączyć funkcje HTML5 (na przykład w celu wyświetlenia kontrolki kalendarza, symbolu waluty odpowiedniego dla ustawień regionalnych, linków poczty e-mail itp.).
- Domyślnie przeglądarka renderuje dane przy użyciu poprawnego formatu na podstawie ustawień regionalnych.
- Atrybut DataType może umożliwić MVC wybranie odpowiedniego szablonu pola do renderowania danych ( format DisplayFormat , jeśli jest używany przez siebie przy użyciu szablonu ciągu). Aby uzyskać więcej informacji, zobacz szablony ASP.NET MVC 2 Brada Wilsona. (Chociaż został napisany dla MVC 2, ten artykuł nadal dotyczy bieżącej wersji ASP.NET MVC).
Jeśli używasz atrybutu DataType
z polem daty, musisz również określić DisplayFormat
atrybut, aby upewnić się, że pole jest poprawnie renderowane w przeglądarkach chrome. Aby uzyskać więcej informacji, zobacz ten wątek StackOverflow.
Uwaga
Sprawdzanie poprawności w trybie jQuery nie działa z atrybutem Zakres i datą/godziną. Na przykład poniższy kod zawsze wyświetla błąd weryfikacji po stronie klienta, nawet jeśli data znajduje się w określonym zakresie:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
Aby użyć atrybutu Range z wartością DateTime, należy wyłączyć walidację daty jQuery. Zazwyczaj nie jest dobrym rozwiązaniem do kompilowania dat twardych w modelach, dlatego nie zaleca się używania atrybutu Range i daty/godziny .
Poniższy kod przedstawia łączenie atrybutów w jednym wierszu:
public class Movie
{
public int ID { get; set; }
[Required,StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[Display(Name = "Release Date"),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; }
[Required,StringLength(5)]
public string Rating { get; set; }
}
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