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 中实现验证逻辑,保持控制器简洁并返回结构化的错误响应。

相关推荐
稚辉君.MCA_P8_Java1 分钟前
Gemini永久会员 Go 实现动态规划
数据结构·后端·算法·golang·动态规划
E***U94513 分钟前
C在物联网中的.NET Core
物联网·.netcore
SimonKing37 分钟前
你的IDEA还缺什么?我离不开的这两款效率插件推荐
java·后端·程序员
武子康1 小时前
大数据-165 Apache Kylin Cube7 实战:聚合组/RowKey/编码与体积精度对比
大数据·后端·apache kylin
qinyia1 小时前
WisdomSSH解决因未使用Docker资源导致的磁盘空间不足问题
运维·服务器·人工智能·后端·docker·ssh·github
庄宿正1 小时前
【Vue2+SpringBoot+SM2】Vue2 + Spring Boot 实现 SM2 双向非对称加密完整实战
java·spring boot·后端
A***F1571 小时前
使用 Spring Boot 实现图片上传
spring boot·后端·状态模式
William_cl1 小时前
【ASP.NET Core】Controller 层 Action 返回值精讲:JsonResult(AJAX 交互核心)
ajax·asp.net·交互
间彧2 小时前
分享一些ServBay和Docker混合使用的最佳实践?
后端