Asp.Net Core FluentValidation校验框架

文章目录


前言

FluentValidation 是一个流行的 .NET 库,用于构建强类型的验证规则。它通常用于验证领域模型DTO 等对象。
注意 :在ASP.NET Core 中,我们可以使用FluentValidation.AspNetCore包来更好地集成,它提供了自动验证的功能,这样我们就不需要在每个Action中手动调用验证了。

一、使用步骤

1.安装 NuGet 包

  1. 执行命令

    csharp 复制代码
    Install-Package FluentValidation.AspNetCore

2.创建模型

  1. UserRequest.cs

    csharp 复制代码
    namespace HostedService.Entity.ResOrReqEntity
    {
        public class UserRequest
        {
            public long Id { get; set; }
    
            public string UserName { get; set; }
            public string Email {  get; set; }
    
            public string Password { get; set; }
    
            public string PasswordAgain {  get; set; }
        }
    }

3.创建验证器

  1. UserRequestValidate.cs

    csharp 复制代码
    using FluentValidation;
    using HostedService.Entity;
    using HostedService.Entity.ResOrReqEntity;
    using Microsoft.AspNetCore.Http.HttpResults;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    
    namespace HostedService.ValidateService
    {
        public class UserRequestValidate : AbstractValidator<UserRequest>
        {
            private readonly UserManager<User> _user;
            public UserRequestValidate(UserManager<User> user)
            {
                _user= user;      
    
                RuleFor(x => x.Email).NotNull().EmailAddress()
                    .WithMessage("邮箱不合法")
                    .Must(x => x.EndsWith("@163.com") || x.EndsWith("@qq.com"))
                    .WithMessage("邮箱只支持163或QQ邮箱");
                RuleFor(x => x.UserName).NotNull().Length(3, 10)
                    .WithMessage("用户名长度需要为3-10个")
                    .MustAsync(FindUserByNameAsync)
                    //.MustAsync(async (x, _) => await user.FindByNameAsync(x) == null)
                    .WithMessage("用户已存在");
    
                RuleFor(x => x.Password).Equal(x => x.PasswordAgain)
                    .WithMessage("两次输入的密码必须一致");
    
            }
            private async Task<bool> FindUserByNameAsync(string name, CancellationToken  token)
            {
                var res=await _user.FindByNameAsync(name);
                return res == null;
            }
        }
    }

4.配置 Program.cs

  1. Program.cs
csharp 复制代码
 // 注册验证器(使用异步支持)
builder.Services.AddValidatorsFromAssemblyContaining<Program>(ServiceLifetime.Scoped);
// 自定义验证错误响应
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        var errors = context.ModelState
            .Where(e => e.Value.Errors.Count > 0)
            .ToDictionary(
                kvp => kvp.Key,
                kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
            );

        return new BadRequestObjectResult(new
        {
            Status = 400,
            Message = "Validation failed",
            Errors = errors
        });
    };
});

5.创建控制器

  1. TestController.cs

    csharp 复制代码
    using HostedService.Entity;
    using HostedService.Entity.ResOrReqEntity;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    
    namespace HostedService.Controllers
    {
        [Route("api/[controller]/[action]")]
        [ApiController]
        public class TestController : ControllerBase
        {
            private readonly UserManager<User> _userManager;
            private readonly RoleManager<Role> _roleManager;
            private readonly IWebHostEnvironment _webHostEnvironment;
    
            public TestController(UserManager<User> userManager, RoleManager<Role> roleManager, IWebHostEnvironment webHostEnvironment)
            {
                _userManager = userManager;
                _roleManager = roleManager;
                _webHostEnvironment = webHostEnvironment;
            }
            
                 [HttpPost]
    	     public async Task<IActionResult> Add(UserRequest userRequest, [FromServices] IValidator<UserRequest> validator)
    	     {
    	     	 //手动出发验证
    	         var validateRes =await validator.ValidateAsync(userRequest);
    	         if (!validateRes.IsValid)
    	         {
    	             return BadRequest(validateRes.ToDictionary());
    	         }
    	         User user = new User { UserName = userRequest.UserName, Email = userRequest.Email };
    	         await _userManager.CreateAsync(user, userRequest.Password);
    	         return Ok();
    	     }
        }
    }

6.测试结果

  1. 示例
    UserRequest

    csharp 复制代码
    {
      "id": 0,
      "userName": "LGF",
      "email": "1231231@gmail.com",
      "password": "123ggg",
      "passwordAgain": "123gg"
    }

    Response Body

    csharp 复制代码
    Error: response status is 400
    
    Response body
    {
      "Email": [
        "邮箱只支持163或QQ邮箱"
      ],
      "UserName": [
        "用户已存在"
      ],
      "Password": [
        "两次输入的密码必须一致"
      ]
    }

二、常见问题及注意事项

  • 验证器未触发

    • 确保 AddFluentValidation() 在 AddControllers() 之后调用
    • 检查验证器是否在注册的程序集中
  • 生命周期管理

    • 验证器建议注册为 Scoped 生命周期
    • 异步验证中注入的仓储需支持异步操作
  • 混合验证规则优先级

    csharp 复制代码
    RuleFor(x => x.UserName).NotNull().Length(3, 10) //同步验证
    .WithMessage("用户名长度需要为3-10个")
    .MustAsync(FindUserByNameAsync)//异步验证
    .WithMessage("用户已存在");

三、性能优化建议

  • 同步验证优先原则:将轻量级验证(如格式校验)放在同步阶段
  • 异步验证批处理:对需要访问外部资源的验证进行合并查询
  • 验证缓存机制:对高频静态数据(如行政区划)可添加内存缓存

总结

通过以上配置,您可以在 ASP.NET Core 8.0 Web API 中实现验证逻辑,保持控制器简洁并返回结构化的错误响应。

相关推荐
卷毛的技术笔记1 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆1 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪2 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball6162 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_2518364572 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao3 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒4 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰5 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理
Apifox5 小时前
Apifox 5 月更新|Postman 导入优化、Runner 支持非 root 运行、请求代码自动带鉴权
前端·后端·安全
JohnYan5 小时前
工作笔记 - PG分组极值
数据库·后端·postgresql