You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:12:32