Fluent validation custom validation rules
1) how to use my service for validation?
You could use the Must
rule:
RuleFor(x => x.Email)
.NotEmpty()
.WithMessage("Email is required.")
.EmailAddress()
.WithMessage("Invalid email format.")
.Must(userService.IsEmailUnique)
.WithMessage("Email already taken");
2) is it possible to register multiple Regular Expression Rules with different error messages? will it work on client side? (if no, how to create custom validation logic for it?)
No, you can have only one validation type per property
if no, how to create custom validation logic for it?
You could use the Must rule:
RuleFor(x => x.Password)
.Must(password => SomeMethodContainingCustomLogicThatMustReturnBoolean(password))
.WithMessage("Sorry password didn't satisfy the custom logic");
3) is validation on server side will work automatically before model pass in action method, and it is enough to call ModelState.IsValid property, or I need to do something more?
Yes, absolutely. Your controller action could look like this:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (!ModelState.IsValid)
{
// validation failed => redisplay the view so that the user
// can fix his errors
return View(model);
}
// at this stage the model is valid => process it
...
return RedirectToAction("Success");
}
UPDATE:
4) is it possible to access to all properties of model when validate some property? (for example I want to compare Password and ConfirmPassword when register)
Yes, of course:
RuleFor(x => x.ConfirmPassword)
.Equal(x => x.Password)
.WithMessage("Passwords do not match");
a nicer variant is to use a RuleBuilderExtension
:
public static class RuleBuilderExtensions
{
public static IRuleBuilder<T, string> Password<T>(this IRuleBuilder<T, string> ruleBuilder, int minimumLength = 14)
{
var options = ruleBuilder
.NotEmpty().WithMessage(ErrorMessages.PasswordEmpty)
.MinimumLength(minimumLength).WithMessage(ErrorMessages.PasswordLength)
.Matches("[A-Z]").WithMessage(ErrorMessages.PasswordUppercaseLetter)
.Matches("[a-z]").WithMessage(ErrorMessages.PasswordLowercaseLetter)
.Matches("[0-9]").WithMessage(ErrorMessages.PasswordDigit)
.Matches("[^a-zA-Z0-9]").WithMessage(ErrorMessages.PasswordSpecialCharacter);
return options;
}
This way it gets trivial to use:
RuleFor(x => x.Password).Password();