W poprzednim artykule na temat ASP.NET MVC 2 opisałem jak tworzyć widoki. Podczas tworzenia widoku dodania nowego wpisu do księgi gości napotkaliśmy na problem, w którym nie było odpowiedniej walidacji danych i na przykład użytkownik mógł dodać wpis z niepoprawnym formatem adresu email.
W tym wpisie chciałbym pokazać jak można przy wykorzystaniu klas z przestrzeni nazw System.ComponentModel.DataAnnotations zrealizować mechanizm walidacji w aplikacji. Muszę przyznać, jak pierwszy raz spotkałem się z tym podejściem, to od razu bardzo mi się spodobało.
Zanim przejdziemy do dodania walidacji w aplikacji zastanówmy się, w którym miejscu najlepiej walidować dane przychodzące od użytkownika. Pierwsza myśl może być taka: walidujmy dane w interfejsie użytkownika. Pomysł dobry bo użytkownik od razu będzie widział, czy dane podał poprawne, czy nie. Niestety tutaj problemem jest taka sytuacja, w której użytkownik na przykład nie skorzysta z naszego interfejsu i wyśle odpowiednio spreparowane żądanie do serwera. Co wtedy? Dlatego powinniśmy też walidować dane przychodzące do akcji, czy są poprawne. No i do tego dobrze je walidować na poziomie interfejsu, aby użytkownik wiedział co się dzieje. Dlatego warto w tych dwóch miejscach walidować dane przychodzące od użytkownika.
Na pewno teraz sobie myślisz, że głupotą jest trzymanie tych samych reguł walidacyjnych w dwóch różnych miejscach, szczególnie, że jak coś będziemy chcieli zmienić, będziemy musieli edytować reguły w dwóch miejscach. Zapewne sobie myślisz, czy nie ma lepszego rozwiązania? A czemu reguł tych nie zapisać w naszym modelu i wykorzystywać ich w reszcie aplikacji? Tutaj właśnie z pomocą przychodzą nam klasy z przestrzeni nazw System.ComponentModel.DataAnnotations. Dzięki tym klasą możemy sobie zdefiniować reguły walidacyjne na poziomie modelu, a następnie ASP.NET MVC 2 praktycznie same z nich będzie korzystać.
No dobra ale jak to działa? W naszej przykładowej aplikacji mamy jedną kasę modelu – GuestBook. Dla przypomnienia nasza klasa ma takie o to właściwości:
- Id – wymagane i automatycznie uzupełniana przez Linq To Sql
- Nick – wymagane, a w bazie jest ustawiony limit na 50 znaków
- Text – wymagane
- Email – nie wymagane, w bazie jest limit na 150 znaków oraz email powinien mieć odpowiedni format
- AddDate – wymagane, powinna być to data
Aby skorzystać z powyższego mechanizmu walidacji, wystarczy udekorować wybrane właściwości odpowiednimi atrybutami. Dostępna lista atrybutów to:
- Required – zapewnia, że właściwość zostanie uzupełniona
- StringLength – zapewnia, że string będzie miał odpowiednią długość
- Range – zapewnia, że wartość będzie z podanego przedziału
- DataType – zapewnia, że właściwość będzie określonego typu (np. że będzie numerem telefonu lub adresem url) – definiuje to typ wyliczeniowy DataType
- RegularExpression – umożliwia skorzystania z wyrażenia regularnego do walidacji danych
- CustomValidation – umożliwia skorzystania z własnej metody z jakieś klasy to walidacji danych
Jak już wiemy, jakie do dyspozycji mamy atrybuty i jak mniej więcej z nich korzystać wystarczy ich teraz użyć. Niestety w tym momencie napotkamy problem: nasza klasa GuestBook jest wygenerowana przez Linq To Sql i gdy zmienimy coś na w naszym modelu (np. dodamy kolejną tabelę z bazy) to wprowadzone atrybuty w wygenerowanym pliku zostaną usunięte. Ale na szczęście jest sposób jak to obejść: Po pierwsze można zauważyć, że klasa GuestBook jest klasą patrial, czy że jej definicja może znajdować się w kilku plikach, co wykorzystamy. Nie możemy w innym pliku dodać tych samych właściwości do klasy GuestBook z odpowiednimi atrybutami. Możemy natomiast utworzyć specjalną klasę, w której będą zapisane nasze reguły i klasę tą wykorzystać jako metadane dla klasy wygenerowanej przez Linq To Sql. A zatem bierzmy się do roboty.
Pierw utwórzmy naszą klasę, która będzie opisywać reguły walidacyjne. Nazwijmy sobie ją GuestBookValidation i zdefiniujmy w niej wszystkie właściwości wraz z atrybutami walidacyjnymi. Poniżej znajduje się kod klasy GuestBookValidation:
1: [Bind(Exclude = "Id")]
2: class GuestBookValidation
3: {
4: [Required(ErrorMessage = "Wprowadź nick")]
5: [StringLength(50, ErrorMessage = "Nick nie może być dłuższy niż 50 znaków")]
6: public string Nick { get; set; }
7:
8: [Required(ErrorMessage = "Wprowadź wpis")]
9: public string Text { get; set; }
10:
11: [RegularExpression("\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*", ErrorMessage = "Niepoprawny format emaila")]
12: [StringLength(150, ErrorMessage = "Nick nie może być dłuższy niż 50 znaków")]
13: public string Email { get; set; }
14: }
Nie będę szczegółowo opisywał poszczególnych atrybutów, myślę, że są one dość jasne. Z powyższego kodu wspomnę tylko o dwóch rzeczach: każdy z atrybutów ma właściwość ErrorMessage, która zostanie użyta do wyświetlenie użytkownikowi, gdy dana właściwość nie będzie się walidować. Drugą rzeczą to właściwość całej klasy Bind. Za jego pomocą mówimy kompilatorowi, że nie chcemy, aby wiązał on właściwości Id z GuestBook z właściwościami klasy GuestBookValidation. Wszystkie pozostałe właściwości zostaną połączone i zostaną wykorzystane reguły walidacyjne z klasy GuestBookValidation w klasie GuestBook.
Aby wszystko ładnie działało pozostaje tylko powiedzieć, żeby klasa GuestBook korzystała z klasy GuestBookValidation jako klasy z metadanymi. W tym celu tworzymy korzystamy z tego, że klasa GuestBook jest klasą patrial i gdzieś w projekcie (najlepiej obie klasy wrzucić do katalogu Models) wrzucamy coś takiego:
1: [MetadataType(typeof(GuestBookValidation))]
2: public partial class GuestBook
3: {
4: }
I już możemy cieszyć się z walidacji 
Zobaczmy jak teraz działa formularz dodania nowego wpisu. Gdy klikniemy w przycisk Create bez wypełnionych pól to zobaczymy coś takiego:

Czyli jak widać walidacja działa, a do tego wyświetlają się odpowiednie komunikaty.
No dobra walidacja działa fajnie, tylko fajnie by było, jak by się formularz walidował przed wysłaniem danych do serwera, aby walidacja odbywała się za pomocą java scriptu. Na szczęście ASP.NET MVC 2 jest nam tutaj bardzo pomocne i bardzo łatwo można to zrealizować. Wystarczy dodać do widoku Create (np. tuż przed formularzem) coś takiego:
1: <script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
2: <script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
3: <%Html.EnableClientValidation(); %>
I możemy się cieszyć walidacją po stronie klienta, prawda, że fajne?
Tags: asp.net mvc,
mvc,
walidacja
Categories: Techniczne
88fef50c-0bf1-4349-a106-8718e0334f74|1|4.0