W poprzednim wpisie wytłumaczyłem, w jaki sposób można wykorzystać bibliotekę Fluent Validation do zorganizowania walidacji danych w aplikacji. W tym natomiast pokażę, w jaki sposób stworzyć w Fluent Validation własny walidator.
W walidatorze możemy użyć metody Must do definiowania własnej logiki walidacji (jak to było zrobione na przykładzie walidacji NIP-u). W większości przypadków takie podejście jest wystarczające. Czasami, gdy jakąś logikę musimy współdzielić między różnymi walidatorami w aplikacji (lub nawet między różnymi aplikacjami), możemy stworzyć walidator, którego później użyjemy tak, jak wbudowanych metod w stylu NotNull. Służy do tego property walidator, o którym będzie mowa w tym wpisie.
PropertyValidator
Myślę, że najlepiej od razu zacząć od przykładu:
public class NipValidator : PropertyValidator | |
{ | |
public NipValidator() | |
: base("{PropertyName} ma niepoprawny format NIPu.") | |
{ | |
} | |
protected override bool IsValid(PropertyValidatorContext context) | |
{ | |
var nip = context.PropertyValue as string; | |
if (nip == null) | |
{ | |
return false; | |
} | |
return NipValidate(nip); | |
} | |
private bool NipValidate(string nip) | |
{ | |
if (nip.Length != 10) | |
{ | |
return false; | |
} | |
return true; | |
} | |
} |
Jak widać na listingu, aby utworzyć własny walidator, wystarczy utworzyć zwykłą klasę i dziedziczyć po klasie PropertyValidator. Logikę walidacji dodajemy do nadpisanej metody IsValid, z której zwracamy true lub false w zależności od tego, czy wartość jest poprawna, czy nie.
Warto dodać jeszcze w konstruktorze domyślną wiadomość, która będzie wyświetlana. W wiadomości możemy skorzystać z parametru {PropertyName}, który zostanie później zamieniony na nazwę walidowanej właściwości.
Mając już gotowy walidator, wystarczy dodać jeszcze pomocniczą metodę, która umożliwi nam skorzystanie z fluent api w docelowym walidatorze. Do tego celu wykorzystamy extension method:
public static class IRuleBuilderExtensions | |
{ | |
public static IRuleBuilderOptions<T, TProperty> Nip<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder) | |
{ | |
return ruleBuilder.SetValidator(new NipValidator()); | |
} | |
} |
Metoda jest bardzo prosta – wystarczy skorzystać w niej z metody SetValidator i przekazać instancję utworzonego property validatora.
Użycie własnego walidatora
Po tych zabiegach możemy już zrezygnować z metody Must w walidatorze do walidacji NIP-u i możemy skorzystać z nowej metody:
RuleFor(u => u.Nip) | |
.Nip(); |
Dzięki takiemu rozwiązaniu możemy w naszych projektach przygotować standardowe walidatory, które następnie wrzucimy do lokalnego nugeta i wykorzystamy w wielu naszych projektach.
Kod przykładu można znaleźć na githubie.
Chciałbym jeszcze zwrócić uwagę na to, że powyższy walidator nie jest poprawną logiką walidacji NIP-u i służy tylko jako przykład tego, w jaki sposób można napisać własny walidator.
1 thought on “Fluent Validation – własny walidator”