FluentValidation自定义验证消息被系统默认消息覆盖问题求助
FluentValidation自定义验证消息被系统默认消息覆盖的解决方案
问题现象
使用FluentValidation为SignUpViewModel配置自定义验证消息时,仅部分场景能正常显示自定义的土耳其语提示;提交空表单时,系统会自动生成英文默认验证消息,覆盖自定义内容。尝试使用NotNull()、NotEmpty()方法均无法解决,将ViewModel属性设为可空类型时问题消失,但希望保留属性非可空的前提下解决该问题。
相关代码
ViewModel代码
public class SignUpViewModel { public string UserName { get; set; } public string Email { get; set; } public string Password { get; set; } }
验证器代码
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>
原因分析
ASP.NET Core会优先执行内置的数据注解验证,对于非可空的字符串属性,当提交空值时,系统会自动添加英文的默认验证消息到ModelState中。之后执行的FluentValidation规则虽然也会生成自定义消息,但ModelState中已有默认消息,最终页面显示的是先添加的默认内容。
解决步骤
1. 禁用ASP.NET Core默认数据注解验证
在Program.cs中配置FluentValidation时,关闭系统默认的验证逻辑,确保仅执行FluentValidation的规则:
builder.Services.AddControllersWithViews() .AddFluentValidation(fv => { fv.DisableDataAnnotationsValidation = true; // 关闭默认数据注解验证 fv.RegisterValidatorsFromAssemblyContaining<SignUpVMValidator>(); // 自动注册当前程序集内的所有验证器 });
2. 优化FluentValidation规则顺序
对于字符串类型的非空验证,NotEmpty()同时覆盖了NotNull()(检查null)和空字符串的场景,因此只需保留NotEmpty()并将其放在规则链的最前面,确保优先触发自定义消息:
public class SignUpVMValidator : AbstractValidator<SignUpViewModel> { public SignUpVMValidator() { RuleFor(x => x.UserName) .NotEmpty().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) .NotEmpty().WithMessage("Şifre Boş Bırakılamaz") .MinimumLength(6).WithMessage("Şifre Minimum 6 Karakterden Oluşmalıdır") .MaximumLength(20).WithMessage("Şifre Maksimum 20 Karakterden Oluşmalıdır"); RuleFor(x => x.Email) .NotEmpty().WithMessage("Email Boş Bırakılamaz") .EmailAddress().WithMessage("Geçerli bir email adresi giriniz"); } }
3. 确保验证器正确注册
如果未使用自动注册方式,需手动在Program.cs中注册验证器:
builder.Services.AddScoped<IValidator<SignUpViewModel>, SignUpVMValidator>();
完成以上配置后,提交空表单时会正常显示自定义的土耳其语验证消息,无需将ViewModel属性设为可空类型。
内容的提问来源于stack exchange,提问作者Berk KARASU
相关产品推荐
相关产品推荐

