【个人博客搭建】(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、拓展:自定义一个处理方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/595539.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python ArcPy批量将大量栅格文件的投影坐标系转为地理坐标系

本文介绍基于Python语言中的ArcPy模块&#xff0c;批量将多个遥感影像由投影坐标系转为地理坐标系的方法。 在之前的文章中&#xff0c;我们介绍过将单独1景遥感影像的投影坐标系转为地理坐标系的方法&#xff0c;大家可以参考文章投影坐标系转为地理坐标系&#xff1a;GDAL命令…

Voice Conversion、DreamScene、X-SLAM、Panoptic-SLAM、DiffMap、TinySeg

本文首发于公众号&#xff1a;机器感知 Voice Conversion、DreamScene、X-SLAM、Panoptic-SLAM、DiffMap、TinySeg Converting Anyones Voice: End-to-End Expressive Voice Conversion with a Conditional Diffusion Model Expressive voice conversion (VC) conducts speak…

【爬虫】爬取A股数据写入数据库(一)

1. 对东方财富官网的分析 步骤&#xff1a; 通过刷新网页&#xff0c;点击等操作&#xff0c;我们发现https://datacenter-web.eastmoney.com/api/data/v1/get?请求后面带着一些参数即可以获取到相应数据。我们使用python来模拟这个请求即可。 我们以如下选择的页面为切入点…

滑动窗口 | 1652. 拆炸弹 |LeetCode

文章目录 题目介绍暴力(可以过力扣竟然。不愧是简单题)&#xff1a;滑动窗口 祝你天天开心 题目介绍 你有一个炸弹需要拆除&#xff0c;时间紧迫&#xff01;你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。 为了获得正确的密码&#xff0c;你需要替换掉每…

关系型数据库MySql分库分表带来的问题以及解决方案

水平分表 水平分表是什么&#xff1f; 将一张表横向拆分为多张表&#xff0c;拆分的表&#xff0c;依然在同一个库中。 例如&#xff0c;user表有400w条记录&#xff0c;将user表拆分成4张表&#xff0c;每张表100w条记录。拆分后的表名&#xff0c;分别叫做user_0、user1、u…

内网用户是如何连接上互联网的?详解NAT网络地址转换技术

背景 https://blog.csdn.net/weixin_43972437/article/details/107344633 不知道你有没有过困惑&#xff0c;都说现在 ipv4 地址耗尽了&#xff0c;但是我们为什么还能上网呢&#xff1f;原来这都要归功于 NAT 网络地址转换技术。 比如我们接入了中国移动的宽带&#xff0c;宽…

重学SpringBoot3-SPI机制

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SPI机制 什么是 SPI&#xff1f;Spring Boot 中的 SPI 机制spring.factories 文件自动配置的实现启动流程中的作用 SPI实际应用步骤 1: 新建模块步骤 2:…

扩展学习|一文读懂知识图谱

一、知识图谱的技术实现流程及相关应用 文献来源&#xff1a;曹倩,赵一鸣.知识图谱的技术实现流程及相关应用[J].情报理论与实践,2015, 38(12):127-132. &#xff08;一&#xff09;知识图谱的特征及功能 知识图谱是为了适应新的网络信息环境而产生的一种语义知识组织和服务的方…

HarmonyOS开发案例:【卡片二级联动】

1 卡片介绍 使用ArkTS语言&#xff0c;实现一个导航与内容二级联动的效果。 2 标题 二级联动&#xff08;ArkTS&#xff09; 3 介绍 介绍了如何基于List组件实现一个导航和内容的二级联动效果。样例主要包含以下功能&#xff1a; 切换左侧导航&#xff0c;右侧滚动到对应…

自定义类型②③——联合体和枚举

自定义类型②③——联合体和枚举 1.联合体1.1 联合体类型的声明1.2 联合体的特点1.3 相同成员结构体和联合体的对比1.4 联合体大小的计算1.5 联合体的应用①1.5 联合体的应用② 2. 枚举2.1 枚举类型的声明2.2 枚举类型的特点2.3 枚举的优点 1.联合体 1.1 联合体类型的声明 关…

Python sqlite3库 实现 数据库基础及应用 输入地点,可输出该地点的爱国主义教育基地名称和批次的查询结果。

目录 【第11次课】实验十数据库基础及应用1-查询 要求: 提示: 运行结果&#xff1a; 【第11次课】实验十数据库基础及应用1-查询 声明&#xff1a;著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 1.简答题 数据库文件Edu_Base.db&#…

有什么方便的教学口语软件?6个软件教你快速练习口语

有什么方便的教学口语软件&#xff1f;6个软件教你快速练习口语 以下是六个方便实用的教学口语软件&#xff0c;它们可以帮助您快速练习口语&#xff1a; AI外语陪练: 这是一款知名的语言学习软件&#xff0c;提供多种语言的口语练习课程。它采用沉浸式的学习方法&#xff0…

【数字图像处理笔记】Matlab实现图像平滑算法 均值-中值-高斯滤波 (三)

&#x1f48c; 所属专栏&#xff1a;【数字图像处理笔记】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x…

jetson实操(二):jetson nano发送短信到指定用户

文章目录 一、准备工作二、代码实现 一、准备工作 腾讯云网址&#xff1a;点击 注&#xff1a;需先申请“短信签名”和“短信正文”&#xff0c;按照要求填写申请即可&#xff0c;腾讯云的审核效率还是很快的&#xff0c;一般在1-2个小时内就会有结果&#xff0c;链接&…

2024-2034年,量子密码市场年增长率将达29.3%

Visiongain发布了一份新报告&#xff0c;题为《2024-2034年量子密码市场报告》&#xff1a;按组件&#xff08;软件、硬件&#xff09;、软件&#xff08;加密算法、密钥管理解决方案等&#xff09;、硬件&#xff08;量子密钥分发&#xff08;QKD&#xff09;设备、量子随机数…

CkickHouse JDBC 使用整理

1. pom 引入 <dependency><groupId>com.clickhouse</groupId><artifactId>clickhouse-jdbc</artifactId><version>0.4.6</version></dependency><dependency><groupId>org.roaringbitmap</groupId><arti…

BeautifulSoup库TapTap评论爬虫

最近在写关于评论数据主题建模和情感分析的作业&#xff0c;本来想用八爪鱼直接爬TapTap的评论数据&#xff0c;但是自动识别网页总是定位错误&#xff0c;还是回归BeautifulSoup和Request来进行评论内容的爬取&#xff0c;具体操作步骤如下 导入所需的库 import re import r…

定制旁通式孔板流量计需要哪些技术参数

旁通式孔板流量计又称桥式孔板流量计&#xff0c;本产品含有直管&#xff0c;直管中安装有孔板&#xff0c;该孔板两侧的直管壁上分别设置一个测量管&#xff0c;其特征是&#xff1a;所述直管和一个桥管并联式连接&#xff0c;二者内管相互连通&#xff0c;并且所述直管和桥管…

mars3d的config,json文件配置谷歌影像地图的tilingScheme属性

mars3d的config,json文件配置tilingScheme属性说明&#xff1a; 1.cesium加载谷歌影像地图的时候需要配置tilingScheme参数&#xff0c;如以下代码&#xff1a; var viewer new Cesium.Viewer("cesiumContainer", { animation: false, //是否显示动画控件 baseLaye…

64位Office API声明语句第118讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…
最新文章