Asp.Net Core FluentValidation校验框架
文章目录
- 前言
- 一、使用步骤
- 1.安装 NuGet 包
- 2.创建模型
- 3.创建验证器
- 4.配置 Program.cs
- 5.创建控制器
- 6.测试结果
- 二、常见问题及注意事项
- 三、性能优化建议
- 总结
前言
FluentValidation 是一个流行的 .NET 库,用于构建强类型的验证规则。它通常用于验证领域模型、DTO等对象。
注意:在ASP.NET Core中,我们可以使用FluentValidation.AspNetCore包来更好地集成,它提供了自动验证的功能,这样我们就不需要在每个Action中手动调用验证了。
一、使用步骤
1.安装 NuGet 包
- 执行命令
Install-Package FluentValidation.AspNetCore
2.创建模型
- UserRequest.cs
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.创建验证器
- UserRequestValidate.cs
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
- Program.cs
// 注册验证器(使用异步支持)
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.创建控制器
-
TestController.cs
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.测试结果
- 示例
UserRequest
Response Body{"id": 0,"userName": "LGF","email": "1231231@gmail.com","password": "123ggg","passwordAgain": "123gg" }
Error: response status is 400Response body {"Email": ["邮箱只支持163或QQ邮箱"],"UserName": ["用户已存在"],"Password": ["两次输入的密码必须一致"] }
二、常见问题及注意事项
- 验证器未触发
- 确保 AddFluentValidation() 在 AddControllers() 之后调用
- 检查验证器是否在注册的程序集中
- 生命周期管理
- 验证器建议注册为 Scoped 生命周期
- 异步验证中注入的仓储需支持异步操作
- 混合验证规则优先级
RuleFor(x => x.UserName).NotNull().Length(3, 10) //同步验证 .WithMessage("用户名长度需要为3-10个") .MustAsync(FindUserByNameAsync)//异步验证 .WithMessage("用户已存在");
三、性能优化建议
- 同步验证优先原则:将轻量级验证(如格式校验)放在同步阶段
- 异步验证批处理:对需要访问外部资源的验证进行合并查询
- 验证缓存机制:对高频静态数据(如行政区划)可添加内存缓存
总结
通过以上配置,您可以在 ASP.NET Core 8.0 Web API 中实现验证逻辑,保持控制器简洁并返回结构化的错误响应。