ASP.NET Core 中的 FluentValidation:为何每个请求一个验证器才是真正的最佳实践

发布: (2026年2月4日 GMT+8 09:02)
4 min read
原文: Dev.to

Source: Dev.to

FluentValidation 在 ASP.NET Core 中的封面图片:为何每个请求只使用一个验证器才是真正的最佳实践

什么是 FluentValidation?

FluentValidation 是一个流行的 .NET 库,允许你使用 流畅、强类型的语法 来定义验证规则,而不是使用属性或控制器逻辑。

不像这样:

[Required]
[EmailAddress]
public string Email { get; set; }

你可以在单独的验证器类中定义规则:

RuleFor(x => x.Email)
    .NotEmpty()
    .EmailAddress();

这使得 API 模型保持简洁,并将验证移到专门的验证层。

为什么验证不应该写在控制器里

把验证写在控制器中会导致:

  • 逻辑重复
  • 代码难以测试
  • 控制器臃肿
  • 业务规则泄漏到 API 层

FluentValidation 直接集成到 ASP.NET Core 管道中,在控制器执行之前自动运行验证。如果验证失败,框架会返回 400 Bad Request —— 控制器里不需要额外代码。

如何在 ASP.NET Core 中使用 FluentValidation

安装包

dotnet add package FluentValidation
dotnet add package FluentValidation.AspNetCore

创建请求 DTO

public class CreateUserRequest
{
    public string FirstName { get; set; }
    public string Email { get; set; }
    public int Age { get; set; }
}

这只是一个请求 DTO —— 不是数据库实体。

创建验证器

public class CreateUserRequestValidator : AbstractValidator
{
    public CreateUserRequestValidator()
    {
        RuleFor(x => x.FirstName)
            .NotEmpty()
            .MinimumLength(3);

        RuleFor(x => x.Email)
            .NotEmpty()
            .EmailAddress();

        RuleFor(x => x.Age)
            .InclusiveBetween(18, 60);
    }
}

注册 FluentValidation

builder.Services.AddControllers()
    .AddFluentValidationAutoValidation();

builder.Services.AddValidatorsFromAssemblyContaining();

就这么简单。每个请求现在都会自动得到验证。

为什么不要使用通用验证器?

很多开发者会问:“我能为所有请求创建一个通用验证器吗?”

简短回答:不能。

原因:

  • 每个请求都有不同的业务规则
  • 通用验证器会变成上帝类
  • 规则会变成 if/else 混乱
  • 失去类型安全
  • 违背单一职责原则

验证不是通用的——它是针对具体用例的。

行业标准模式

CreateUserRequest      → CreateUserRequestValidator
UpdateUserRequest      → UpdateUserRequestValidator
CreateOrderRequest     → CreateOrderRequestValidator

每个 API 合约都有自己的验证器,带来:

  • 用例级别的清晰规则
  • 便于单元测试
  • 零重复代码
  • 控制器保持简洁
  • 可扩展的架构

在不重复的前提下共享规则

规则扩展

public static class ValidationExtensions
{
    public static IRuleBuilderOptions ValidEmail(
        this IRuleBuilder rule)
    {
        return rule.NotEmpty().EmailAddress();
    }
}

使用方式

RuleFor(x => x.Email).ValidEmail();

这样既保持验证器的简洁和可复用,又不破坏架构。

最后思考

FluentValidation 不仅仅是一个验证工具——它是一种设计决策。通过使用:

  • 请求 DTO
  • 每个请求一个验证器
  • 自动管道验证

你可以构建出:

  • 更安全
  • 更清晰
  • 更易测试
  • 更易维护

这才是实际生产环境中 .NET 系统的模样。

Back to Blog

相关文章

阅读更多 »