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

【个人博客搭建】(17)使用FluentValidation 参数校验

FluentValidation 是一个用于 .NET 的开源验证库,它提供了一种流畅的接口和强类型验证规则,使得验证逻辑表达得更加清晰和简洁。(Apache-2.0)

FluentValidation 的主要作用包括:

  1. 提高代码可读性:通过使用 Fluent 接口和 lambda 表达式,FluentValidation 能够让验证逻辑更容易被阅读和理解。
  2. 简化验证逻辑编写:它允许开发者以声明式的方式构建复杂的验证规则,这样可以减少编写重复性验证代码的工作量。
  3. 易于维护:由于验证规则是强类型的,这使得维护和重构变得更加容易,因为编译器可以帮助检查类型安全。
  4. 支持 .NET 8:FluentValidation 更新迅速,与 .NET 8 保持同步,确保了在新平台上的可用性。
  5. 自定义错误消息:FluentValidation 允许开发者为每个验证规则定义自定义的错误消息,这样可以提供更具体的错误反馈给最终用户。
  6. 扩展性强:如果默认提供的验证规则不满足需求,开发者可以创建自定义的验证器来应对特定的业务逻辑。
  7. 集成灵活:FluentValidation 可以轻松地集成到现有的 .NET Core Web API 或 MVC 项目中,与模型绑定和数据注解无缝协作。

总的来说,FluentValidation 是一个功能强大且易于使用的验证库,它能够帮助 .NET 开发者构建健壮的应用程序,同时保持良好的代码质量和可维护性。

前边我们做了系统登录注册的简单接口,对于参数的处理都是通过代码去编写的,如下:

//验证
if (string.IsNullOrWhiteSpace(para.UserName) || string.IsNullOrWhiteSpace(para.PassWord))
{return ApiResultHelper.Error("请输入账号或密码!");
}

如果其他地方也需要类似的判断处理,则,需要对代码进行复制,复制的地方多了,后续维护的成本也会加大! 

所以,我们希望能有一个统一的处理方式来规划这些值,

于是,便有了对FluentValidation验证体系的使用了。

(五一结束了,也祝各位工作顺利,升职加薪!)

进入正题

1、安装nuget包:FluentValidation 

2、 配置验证规则。

        我这里是把验证模式放在Model层,创建Validation文件夹处理的,也可以放在入参那边的模型下边。

例子:

/// <summary>
/// 用户登录 入参 校验
/// </summary>
public class LoginUserValidator : AbstractValidator<LoginUserParameters>
{public LoginUserValidator(){RuleFor(para => para.UserName).NotEmpty().WithMessage("【用户名】不能为空");RuleFor(para => para.PassWord).NotEmpty().WithMessage("【密码】不能为空");}
}/// <summary>
/// 用户注册 入参 校验
/// </summary>
public class RegisterUserValidator : AbstractValidator<RegisterUserParameters>
{public RegisterUserValidator(){//1.不为空string notEmpty = "不能为空";RuleFor(para => para.UserName).NotEmpty().WithMessage("【用户名】" + notEmpty);RuleFor(para => para.PassWord).NotEmpty().WithMessage("【密码】" + notEmpty);RuleFor(para => para.Email).NotEmpty().WithMessage("【邮箱】" + notEmpty);RuleFor(para => para.AuthCode).NotEmpty().WithMessage("【验证码】" + notEmpty);//2.数据库存储长度限制//(ps:可用sugar特性或查询数据库配置统一处理吧)string notLength = "长度有误";RuleFor(para => para.UserName).Length(1, 25).WithMessage("【用户名】" + notLength);RuleFor(para => para.PassWord).Length(6, 18).WithMessage("【密码】" + notLength);RuleFor(para => para.Email).Length(6, 30).WithMessage("【邮箱】" + notLength);//不建议限制RuleFor(user => user.AuthCode).Length(6, 8).WithMessage("【验证码】" + notLength);//3.格式(正则)string notMatches = "格式不正确";RuleFor(user => user.Email).Matches(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").WithMessage("【邮箱】" + notMatches);//可与上边拼接一起}}

        这里一个是简单方式的,一个是验证方式较多的。

        如有其他需要,可自行百度或搜索其他方式方法。

3、注入服务

builder.Services.AddTransient<IValidator<LoginUserParameters>, LoginUserValidator>();
builder.Services.AddTransient<IValidator<RegisterUserParameters>, RegisterUserValidator>();

4、使用。

        4.1、控制器层注入

 private readonly ILogger<UsersController> _logger;private readonly IUsersService _usersService;//参数验证private readonly IValidator<LoginUserParameters> _loginUserParametersValidator;private readonly IValidator<RegisterUserParameters> _registerUserParametersValidator;/// <summary>/// 构造函数/// </summary>/// <param name="logger"></param>public UsersController(ILogger<UsersController> logger, IUsersService usersService,IValidator<LoginUserParameters> loginUserParametersValidator,IValidator<RegisterUserParameters> registerUserParametersValidator){_logger = logger;_usersService = usersService;_loginUserParametersValidator = loginUserParametersValidator;_registerUserParametersValidator = registerUserParametersValidator;}

        4.2、方法Action中使用

 var validationResult = _loginUserParametersValidator.Validate(para);if (!validationResult.IsValid){//return BadRequest(validationResult.Errors);var errs = validationResult.Errors;var errsStr = string.Empty;var index = 1;validationResult.Errors.ForEach(t =>{errsStr = errsStr + index.ToString() + "、" + t.ToString() + ";";index ++;});return ApiResultHelper.Error("【参数验证失败】" + errsStr);}

5、测试:

        5.1、如图。(无账号)

        这里把所有有误的都加上来了

        然后,我们通过信息查看,其实为空的是否必然长度是不对的,也就没必要体现出来

        所以,在注入后再添加代码:

//(1)设置模型类的CascadeMode,当模型的第一个验证失败,后续验证不执行。
ValidatorOptions.Global.DefaultClassLevelCascadeMode = CascadeMode.Stop;
//(2)设置模型字段的CascadeMode,当字段的第一个验证失败,后续验证不执行。
ValidatorOptions.Global.DefaultRuleLevelCascadeMode = CascadeMode.Stop;

        这就很符合我们自己写逻辑的规则方式了。        

        继续测试的效果也就是第一个错误提示了。

        最后,在验证那一串循环代码,可以在封装一下,不然也是每次写这么多重复代码。

6、其他:

        6.1、在查询该功能实现及其他处理,可参考文章:

fluentvalidation - 简书

https://www.cnblogs.com/wenthing/p/18006465 

        6.2、拓展:自定义一个处理方式。

相关文章:

【个人博客搭建】(17)使用FluentValidation 参数校验

FluentValidation 是一个用于 .NET 的开源验证库&#xff0c;它提供了一种流畅的接口和强类型验证规则&#xff0c;使得验证逻辑表达得更加清晰和简洁。&#xff08;Apache-2.0&#xff09; FluentValidation 的主要作用包括&#xff1a; 提高代码可读性&#xff1a;通过使用 F…...

数据结构===散列表

文章目录 概要散列思想散列函数散列冲突开放寻址法装载因子 链表法 代码Java小结 概要 散列表是一种很有趣的数据结构。 散列表是一个很有用的数据结构。它是数组演练而来的&#xff0c;又是一个基于数组的扩展的数据结构。接下来看看。 散列思想 散列表用的是数组支持按照下…...

10G MAC层设计系列-(2)MAC RX模块

一、概述 MAC RX模块的需要进行解码、对齐、CRC校验。 因为在空闲的时候10G PCS/PMA会一直向外吐空闲符&#xff08;x07&#xff09;所以需要根据开始符、结束符将有效数据从码流中截取&#xff0c;也就是解码。 因为开始字符的所在位置有两种形式&#xff0c;而结束字符的位…...

解码Starknet Verifier:深入逆向工程之旅

1. 引言 Sandstorm为&#xff1a; 能提交独立proof给StarkWare的Ethereum Verifier&#xff0c;的首个开源的STARK prover。 开源代码见&#xff1a; https://github.com/andrewmilson/sandstorm&#xff08;Rust&#xff09; L2Beat 提供了以太坊上Starknet的合约架构图&…...

【C++语言】类和对象--默认成员函数 (中)

文章目录 前言类的六个默认成员函数&#xff1a;1. 构造函数概念特性做了什么&#xff1f;易错注意&#xff1a;显式定义和默认构造函数 2. 析构函数概念特征做了什么?注意事项&#xff1a; 3.拷贝构造函数概念特征做了什么&#xff1f;注意事项&#xff1a; 4.赋值运算符重载…...

前端递归常见应用

概览 在 JavaScript 中&#xff0c;递归是一种编程技术&#xff0c;指的是函数直接或间接调用自身的过程。 递归通常用于解决可以分解为相同子问题的问题。通过不断地将问题分解成更小的、相似的子问题&#xff0c;直到达到某种基本情况&#xff08;不再需要进一步递归的简单情…...

AI工具如何改变我们的工作与生活

AI工具在当今社会中扮演着越来越重要的角色&#xff0c;它们已经开始改变着我们的工作方式和生活方式。在接下来的2000字篇幅中&#xff0c;我将详细探讨AI工具如何影响我们的工作和生活。 AI工具在工作中的影响&#xff1a; 自动化和智能化生产流程&#xff1a; AI工具可以通…...

深入了解C/C++的内存区域划分

&#x1f525;个人主页&#xff1a;北辰水墨 &#x1f525;专栏&#xff1a;C学习仓 本节我们来讲解C/C的内存区域划分&#xff0c;文末会附加一道题目来检验成果&#xff08;有参考答案&#xff09; 一、大体有哪些区域&#xff1f;分别存放什么变量开辟的空间&#xff1f; …...

C++构造函数和析构函数的调用顺序

一般情况下&#xff0c;调用析构函数的次序正好与调用构造函数的次序相反&#xff0c;也就是最先被调用的构造函数&#xff0c;其对应的析构函数最后被调用&#xff0c;而最后被调用的构造函数&#xff0c;其对应的析构函数最先被调用。 当然对象的构造函数和析构函数调用时机和…...

智能家居1 -- 实现语音模块

项目整体框架: 监听线程4&#xff1a; 1. 语音监听线程:用于监听语音指令&#xff0c; 当有语音指令过来后&#xff0c; 通过消息队列的方式给消息处理线程发送指令 2. 网络监听线程&#xff1a;用于监听网络指令&#xff0c;当有网络指令过来后&#xff0c; 通过消息队列的方…...

Leetcode 3139. Minimum Cost to Equalize Array

Leetcode 3139. Minimum Cost to Equalize Array 1. 解题思路2. 代码实现 题目链接&#xff1a;3139. Minimum Cost to Equalize Array 1. 解题思路 这一题是一道hard的题目&#xff0c;而且看了一下答出率低的离谱&#xff0c;就一开始被吓到了&#xff0c;不过实际做了一下…...

【element-ui】el-table横向滚动后,通过is-scrolling-left获取滚动高度失效的问题

el-table横向滚动后&#xff0c;通过is-scrolling-left获取滚动高度失效的问题 需求 现在有一个需求&#xff0c;需要监听el-table的纵向滚动&#xff0c;当滚动高度达到特定值时进行一些操作。 代码如下&#xff1a; methods:{throttledHandleScroll() {// 如果已经有定时器…...

JAVA中的日期

获取当前的日期 LocalDate LocalDate today LocalDate.now();System.out.println("今天是:"today);//今天是:2024-05-06String format today.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));System.out.println("今天是&#xff1a;"…...

一起了解开源自定义表单的优势表现

随着社会的进步和科技的发展&#xff0c;越来越多的中小企业希望采用更为先进的软件平台&#xff0c;助力企业实现高效率的流程化管理。低代码技术平台、开源自定义表单已经慢慢走入大众视野&#xff0c;成为一款灵活、高效的数字化转型工具。流辰信息专注于低代码技术平台的研…...

体育老师工资高吗,奖金有吗

教师的薪资水平与多种因素相关&#xff0c;包括教育经验、工作地点、学校类型以及个人的教学成果等。在讨论体育教师的工资问题时&#xff0c;不能仅仅关注数字&#xff0c;更应了解教育价值和个人发展。 初中体育教师的工资水平受多种因素影响。根据网络统计的数据&#xff0c…...

Linux驱动开发——(十一)INPUT子系统

目录 一、input子系统简介 二、input驱动API 2.1 input字符设备 2.2 input_dev结构体 2.3 上报输入事件 2.4 input_event结构体 三、代码 3.1 驱动代码 3.2 测试代码 四、平台测试 一、input子系统简介 input子系统是管理输入的子系统&#xff0c;和pinctrl、gpio子…...

大数据毕业设计Python+Django旅游景点评论数据采集分析可视化系统 NLP情感分析 LDA主题分析 bayes分类 旅游爬虫 旅游景点评论爬虫 机器学习 深度学习 人工智能 计算机毕业设计

毕业论文&#xff08;设计&#xff09;开题报告 学生姓名 学 号 所在学院 信息工程学院 专 业 指导教师姓名 指导教师职称 工程师 助教 指导教师单位 论文&#xff08;设计&#xff09;题目 基于朴素贝叶斯算法旅游景点线上评价情感分析 开 题 报 告…...

FSNotes for Mac v6.7.1中文激活版:强大的笔记管理工具

FSNotes for Mac是一款功能强大的文本处理与笔记管理工具&#xff0c;为Mac用户提供了一个直观、高效的笔记记录和整理平台。 FSNotes for Mac v6.7.1中文激活版下载 FSNotes支持Markdown语法&#xff0c;使用户能够轻松设置笔记格式并添加链接、图像等元素&#xff0c;实现笔记…...

课程34:Windows Docker部署.Net Core项目

这里写目录标题 🚀前言一、安装Docker Desktop1.1 官网下载Docker1.2 安装Docker1.2.1 选择配置,默认都勾选1.2.2 安装中1.2.3 安装成功1.2.4 启动1.2.5 启动成功二、.Net Core 项目发布与部署2.1 修改Dockerfile文件2.2 Web项目发布2.3 修改配置2.3.1 修改dockerfile<...

分布式与一致性协议之ZAB协议(四)

ZAB协议 ZooKeeper是如何选举领导者的。 首先我们来看看ZooKeeper是如何实现成员身份的&#xff1f; 在ZooKeeper中&#xff0c;成员状态是在QuorumPeer.java中实现的&#xff0c;为枚举型变量 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING }其实&…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...