当前位置: 首页 > article >正文

Asp.Net Core FluentValidation校验框架

文章目录

  • 前言
  • 一、使用步骤
    • 1.安装 NuGet 包
    • 2.创建模型
    • 3.创建验证器
    • 4.配置 Program.cs
    • 5.创建控制器
    • 6.测试结果
  • 二、常见问题及注意事项
  • 三、性能优化建议
  • 总结


前言

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

一、使用步骤

1.安装 NuGet 包

  1. 执行命令
    Install-Package FluentValidation.AspNetCore
    

2.创建模型

  1. 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.创建验证器

  1. 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

  1. 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.创建控制器

  1. 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.测试结果

  1. 示例
    UserRequest
    {"id": 0,"userName": "LGF","email": "1231231@gmail.com","password": "123ggg","passwordAgain": "123gg"
    }
    
    Response Body
    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 中实现验证逻辑,保持控制器简洁并返回结构化的错误响应。

相关文章:

Asp.Net Core FluentValidation校验框架

文章目录 前言一、使用步骤1.安装 NuGet 包2.创建模型3.创建验证器4.配置 Program.cs5.创建控制器6.测试结果 二、常见问题及注意事项三、性能优化建议总结 前言 FluentValidation 是一个流行的 .NET 库&#xff0c;用于构建强类型的验证规则。它通常用于验证领域模型、DTO等对…...

CRISPR-Cas系统的小型化研究进展-文献精读137

Progress in the miniaturization of CRISPR-Cas systems CRISPR-Cas系统的小型化研究进展 摘要 CRISPR-Cas基因编辑技术由于其简便性和高效性&#xff0c;已被广泛应用于生物学、医学、农学等领域的基础与应用研究。目前广泛使用的Cas核酸酶均具有较大的分子量&#xff08;通…...

利用python工具you-get下载网页的视频文件

有时候我们可能在一个网站看到一个视频&#xff08;比如B站&#xff09;&#xff0c;想下载&#xff0c;但是页面没有下载视频的按钮。这时候&#xff0c;我们可以借助python工具you-get来实现下载功能。下面简要说下步骤 &#xff08;一&#xff09;因为使用的是python工具&a…...

Wi-Fi 切换 5G 的时机

每天都希望 Wi-Fi 在我离开信号覆盖范围时能尽快切到 5G&#xff0c;但每次它都能坚挺到最后半格信号&#xff0c;我却连看个天气预报都看不了…我不得不手工关闭 Wi-Fi&#xff0c;然后等走远了之后再打开&#xff0c;如此反复&#xff0c;不厌其烦。 早上出门上班&#xff0c…...

【请关注】各类数据库优化,抓大重点整改,快速优化空间mysql,Oracle,Neo4j等

各类数据库优化&#xff0c;抓大重点整改&#xff0c;快速优化&#xff0c;首先分析各数据库查询全部表的空间大小及记录条数的语句&#xff1a; MySQL -- 查看所有表的空间大小 SELECT TABLE_SCHEMA AS 数据库名, TABLE_NAME AS 表名, ENGINE AS 存储引擎, CONCAT(ROUND(DAT…...

Mybatis Plus JSqlParser解析sql语句及JSqlParser安装步骤

MyBatis Plus 整合 JSqlParser 进行 SQL 解析的实现方案&#xff0c;主要包括环境配置和具体应用。通过 Maven 添加mybatis-plus-core 和 jsqlparser 依赖后&#xff0c;可用 CCJSqlParserUtil 解析 SQL 语句&#xff0c;支持对 SELECT、UPDATE 等语句的语法树分析和重构。技术…...

React从基础入门到高级实战:React 高级主题 - 性能优化:深入探索与实践指南

React 性能优化&#xff1a;深入探索与实践指南 引言 在现代Web开发中&#xff0c;尤其是2025年的技术环境下&#xff0c;React应用的性能优化已成为开发者不可忽视的核心课题。随着用户对应用速度和体验的要求日益提高&#xff0c;React应用的规模和复杂性不断增加&#xff…...

负载均衡群集---Haproxy

目录 一、HAproxy 一、概念 二、核心作用 三、主要功能特性 四、应用场景 五、优势与特点 二、 案例分析 1. 案例概述 2. 案例前置知识点 &#xff08;1&#xff09;HTTP 请求 &#xff08;2&#xff09;负载均衡常用调度算法 &#xff08;3&#xff09;常见的 web …...

2025年5月个人工作生活总结

本文为 2025年5月工作生活总结。 研发编码 一个项目的临时记录 月初和另一项目同事向业主汇报方案&#xff0c;两个项目都不满意&#xff0c;后来领导做了调整&#xff0c;将项目合并&#xff0c;拆分了好几大块。原来我做的一些工作&#xff0c;如数据库、中间件等&#xff…...

【stm32开发板】单片机最小系统原理图设计

一、批量添加网络标签 可以选择浮动工具中的N&#xff0c;单独为引脚添加网络标签。 当芯片引脚非常多的时候&#xff0c;选中芯片&#xff0c;右键选择扇出网络标签/非连接标识 按住ctrl键即可选中多个引脚 点击将引脚名称填入网络名 就完成了引脚标签的批量添加 二、电源引…...

实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.2 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第5章析因设计引导5.7节思考题5.2 R语言解题。主要涉及方差分析&#xff0c;正态假设检验&#xff0c;残差分析&#xff0c;交互作用。 dataframe<-data.frame( Surfacec(74,64,60,92…...

2025山东CCPC题解

文章目录 L - StellaD - Distributed SystemI - Square PuzzleE - Greatest Common DivisorG - Assembly Line L - Stella 题目来源&#xff1a;L - Stella 解题思路 签到题&#xff0c;因为给出的字母不是按顺序&#xff0c;可以存起来赋其值&#xff0c;然后在比较。 代码…...

【解决办法】ubuntu重启不起来,输入用户名和密码进不去,又重新返回登录页。

项目场景&#xff1a; ubuntu重启不起来&#xff0c;输入用户名和密码进不去&#xff0c;又重新返回登录页。 问题描述 在华硕天选一代笔记本上面安装了ubuntu22.04.5桌面版&#xff0c;但是重启以后出现&#xff0c;输入了用户名和密码&#xff0c;等待一会还让输入用户名和…...

CentOS Stream 9 中部署 MySQL 8.0 MGR(MySQL Group Replication)一主两从高可用集群

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《MySQL技术精粹》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、MySQL 8.0 中的高可用方案 2、适用场景 二、环境准备 1、系统环境说明…...

pycharm 新UI 固定菜单栏 pycharm2025 中文版

pycharm 新UI 文件 -> 设置 -> 外观与行为 -> 外观 -> UI选项 -> 主菜单:显示在主工具栏上方. 即可固定...

跟单业务和量化交易业务所涉及到的设计模式

&#x1f501; 跟单业务中常用的设计模式&#xff1a; 1. 观察者模式&#xff08;Observer&#xff09; 场景&#xff1a;一个大V下单&#xff0c;系统需要自动通知所有跟随者进行同步下单。好处&#xff1a;解耦下单者与跟随者&#xff0c;支持灵活扩展、异步通知。面试亮点…...

我的世界Java版1.21.4的Fabric模组开发教程(十一)创建方块

这是适用于Minecraft Java版1.21.4的Fabric模组开发系列教程专栏第十一章——创建方块。想要阅读其他内容&#xff0c;请查看或订阅上面的专栏。 方块(Block) 是构成Minecraft世界的主要组成部分&#xff0c;是组成游戏地图的最基本单元&#xff0c;也是模组开发的核心元素之一…...

VR/AR 视网膜级显示破局:10000PPI 如何终结颗粒感时代?

一、传统液晶 “纱窗效应”&#xff1a;VR 沉浸体验的最大绊脚石 当用户首次戴上 VR 头显时&#xff0c;眼前密密麻麻的像素网格往往打破沉浸感 —— 这正是传统液晶显示在近眼场景下的致命缺陷。受限于 500-600PPI 的像素密度&#xff0c;即使达到 4K 分辨率&#xff0c;等效到…...

C++ 命令模式:设计与实现详解

一、引言 在软件开发中,我们经常需要将“请求”或“操作”封装成对象,以便在不同的上下文环境中传递、存储、延迟执行或撤销。命令模式(Command Pattern)正是为解决这类问题而生的行为设计模式。本文将深入探讨 C++ 中命令模式的设计理念、实现方式及其应用场景。 二、命…...

系统思考:化繁为简的艺术

系统思考&#xff0c;其实是一门化繁为简的艺术。当我们能够把复杂的问题拆解成清晰的核心以及更加简单&#xff0c;从而提升团队的思考品质和行动品质&#xff0c;发挥最大的合力。 每个公司都想在某方面成为最优秀的&#xff0c;但是实际上具有穿透性的洞察力和摆脱虚荣心的清…...

java/mysql/ES下的日期类型分析

mysql的timestamp和datetime mysql的TIMESTAMP类型内部存的是unix时间戳&#xff0c;可认为是一个32位的整型&#xff0c;它记录了1970.1.1以来的秒数。因为存储长度4字节的限制&#xff0c;所以有2038年限制。 DATETIME类型内部存的是long型&#xff0c;记录了1000.1.1以来的…...

Angularjs-Hello

1 关于Angularjs 最近因为项目需要又要做这个&#xff0c;所以简单复习下。其实这个大概7&#xff0c;8年前就用过&#xff0c;当时做了几个简单页面觉得太简单就还是回去做嵌入式了。按照互联网技术的进化速度&#xff0c;本来以为早死在 沙滩上了&#xff0c;没想到现在还在坚…...

Python训练营---Day41

DAY 41 简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 …...

Linux 1.0.4

父子shell linux研究的就是shell 打开两个窗口就是两个shell 终端的软件有很多 bash也是一个软件 我们在terminal里面再打开一个bash&#xff0c;然后再次使用ps命令发现多出来一个bash&#xff0c;之后点击exit只是显示了一个exit&#xff0c;这个只是退出了在terminal中打开…...

Qt -下载Qt6与OpenCV

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【暂无】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 前言 呃啊&#xff0c;本来就想在 Qt 里简单几个 OpenVC 的函数&#xff0c;没想到一搞就是一天。 我之前的开发环境是 Qt 5.14.2&#xff0c;使用 MinGW 7.3.0 64-bit 编…...

机器学习无监督学习sklearn实战一:K-Means 算法聚类对葡萄酒数据集进行聚类分析和可视化( 主成分分析PCA特征降维)

本项目代码在个人github链接&#xff1a;https://github.com/KLWU07/Machine-learning-Project-practice/tree/main/1-Wine%20cluster%20analysis 如果对于聚类算法理论不理解可参考这篇之前文章机器学习中无监督学习方法的聚类&#xff1a;划分式聚类、层次聚类、密度聚类&…...

可灵2.1 vs Veo 3:AI视频生成谁更胜一筹?

在Google发布Veo 3几天后,可灵显然感受到了压力,发布了即将推出的视频模型系列可灵 2.1的早期体验版。 据我了解,有三种不同的模式: 可灵 2.1 标准模式: 720p分辨率 仅支持图像转视频(生成更快,一致性更好) 5秒视频仍需20积分 可灵 2.1 专业模式: 1080p分辨率 仅在图…...

C语言之编译器集合

C语言有多种不同的编译器&#xff0c;以下是常见的编译工具及其特点&#xff1a; 一、主流C语言编译器 GCC&#xff08;GNU Compiler Collection&#xff09; 特点&#xff1a;开源、跨平台&#xff0c;支持多种语言&#xff08;C、C、Fortran 等&#xff09;。 使用场景&…...

计量表计的演进历程与技术变革:从机械到物联网时代

前言 近期在用python写一些关于计量表计数据集采模型。主要就是针对计量表计采集的相关数据&#xff0c;按照通讯协议格式进行解析&#xff0c;最后根据自己需求&#xff0c;编制界面进行数据的展示&#xff0c;存储&#xff0c;以及运算的内容。现在就个人关于计量表计的一点…...

更换Homebrew 源

以下是查看和修改 Homebrew 源的详细步骤&#xff0c;适用于需要切换到国内镜像以加速下载的场景&#xff1a; 1. 查看当前 Homebrew 源 # 查看 brew 主仓库地址 git -C "$(brew --repo)" remote get-url origin# 查看 homebrew-core 仓库地址 git -C "$(brew…...