Reputation: 71
I used the fluentvalidation library to create validations for my viewmodels. The validation messages I wrote are valid at some points, and at some points they are crushed under another message. I searched how to solve this but couldn't find a definitive solution.
ViewModel
public class SignUpViewModel
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
Validation
public class SignUpVMValidator : AbstractValidator<SignUpViewModel>
{
public SignUpVMValidator()
{
RuleFor(x => x.UserName)
.NotNull().WithMessage("Kullanıcı Adı Boş Bırakılamaz")
.MinimumLength(6).WithMessage("Kullanıcı Adı Minimum 6 Karakterden Oluşmalıdır")
.MaximumLength(20).WithMessage("Kullanıcı Adı Maksimum 20 Karakterden Oluşmalıdır");
RuleFor(x => x.Password)
.MinimumLength(6).WithMessage("Şifre Minimum 6 Karakterden Oluşmalıdır")
.MaximumLength(20).WithMessage("Şifre Maksimum 20 Karakterden Oluşmalıdır")
.NotNull().WithMessage("Şifre Boş Bırakılamaz").NotEmpty().WithMessage("Şifre Boş Bırakılamaz");
RuleFor(x => x.Email)
.NotNull().WithMessage("Email Boş Bırakılamaz")
.EmailAddress();
}
}
Controller
[HttpPost]
public async Task<IActionResult> Index(SignUpViewModel signUpViewModel)
{
if (ModelState.IsValid)
{
AppUser user = signUpViewModel.Adapt<AppUser>();
IdentityResult result = await userManager.CreateAsync(user, signUpViewModel.Password);
if (result.Succeeded)
{
await userManager.AddToRoleAsync(user,"User");
return RedirectToAction("Index", "Login");
}
else
{
AddModelError(result);
}
}
return View(signUpViewModel);
}
Razor
<form asp-action="Index" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="mb-3">
<label class="form-label" asp-for="UserName">Kullanıcı Adı</label>
<input asp-for="UserName" type="text" class="form-control" id="username" placeholder="Kullanıcı Adı">
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="mb-3">
<label class="form-label" asp-for="Email">Mail Adresi</label>
<input asp-for="Email" type="text" class="form-control" id="username" placeholder="Mail Adresi">
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="mb-3">
<label class="form-label" asp-for="Password">Şifre</label>
<input asp-for="Password" type="password" class="form-control" id="userpassword" placeholder="Şifrenizi Oluşturun">
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="mt-3 text-end">
<button class="btn btn-primary w-sm waves-effect waves-light" type="submit">Kayıt Ol</button>
</div>
<div class="mt-4 text-center">
<p class="text-muted mb-0">Zaten Bir Hesabınız Var Mı ? <a href="Login" class="fw-medium text-primary">Giriş Sayfası</a></p>
</div>
</form>
I triggered the form without typing anything in the first photo and the default Annotions returned in English
In the second photo, I got a response as I set it.
What I want is to be able to adjust the Annotations in the first photo as I want. I did this by trying the NotNull()
and NotEmpty()
methods in turn, but without success.
If I make the properties nullable, this problem disappears, I can understand why, but what I'm wondering is how can I override the system's automatic message without making it nullable?
Upvotes: 0
Views: 244
Reputation: 21546
What I want is to be able to adjust the Annotations in the first photo as I want. I did this by trying the NotNull() and NotEmpty() methods in turn, but without success.
This is a compatibility issue when using Asp.net Core build-in Validation and the FluentValidation.
After FluentValidation is executed, any other validator providers will also have a chance to execute. This means you can mix FluentValidation auto-validation with DataAnnotations attributes (or any other ASP.NET ModelValidatorProvider implementation).
And if we disable the Asp.net core DataAnnotations Validation (refer to this article:Compatibility with ASP.NET's built-in Validation), it will still meet your issue, because of the client-side validation.
So, as a workaround, I suggest you can mix FluentValidation auto-validation with DataAnnotations attributes, and set required error message twice, like this:
The DataAnnotations validation:
public class SignUpViewModel
{
[Required(ErrorMessage = "Kullanıcı Adı Boş Bırakılamaz")]
public string UserName { get; set; }
[Required(ErrorMessage = "Email Boş Bırakılamaz")]
public string Email { get; set; }
[Required(ErrorMessage = "Şifre Boş Bırakılamaz")]
public string Password { get; set; }
}
The FluentValidation:
public class SignUpVMValidator : AbstractValidator<SignUpViewModel>
{
public SignUpVMValidator()
{
RuleFor(x => x.UserName)
.NotNull().WithMessage("Kullanıcı Adı Boş Bırakılamaz")
.MinimumLength(6).WithMessage("Kullanıcı Adı Minimum 6 Karakterden Oluşmalıdır")
.MaximumLength(20).WithMessage("Kullanıcı Adı Maksimum 20 Karakterden Oluşmalıdır");
RuleFor(x => x.Password)
.MinimumLength(6).WithMessage("Şifre Minimum 6 Karakterden Oluşmalıdır")
.MaximumLength(20).WithMessage("Şifre Maksimum 20 Karakterden Oluşmalıdır")
.NotNull().WithMessage("Şifre Boş Bırakılamaz").NotEmpty().WithMessage("Şifre Boş Bırakılamaz");
RuleFor(x => x.Email)
.NotNull().WithMessage("Email Boş Bırakılamaz")
.EmailAddress();
}
}
Finally, since this issue relates the FluentValudation, you can also submit a feedback to them, might be they will provide a build-in method to solve this issue.
Upvotes: 1