net6中使用FluentValidation做实体验证(批量注册)

news2024/11/17 13:56:58

实体验证-FluentValidation

首先明白两个概念

  • 自动验证:就是在请求进入到控制器前FluentValidation就自行完成实体的验证并做错误返回,
    • 优点:简单 少一些手动调用的代码
    • 缺点:灵活性差,不好控制,不支持异步等。官方不建议使用自动验证
  • 手动验证:在代码中手动示例验证类,进行调用 并自己判断校验结果 获取错误信息,自行做错误返回控制
    • 优点:控制方便,返回结构可控制
    • 缺点:需要手动创建并传入校验体,重复代码较多(可自己做一次封装,这样就不多了)

如下是官方原文:

With automatic validation, FluentValidation plugs into the validation pipeline that’s part of ASP.NET Core MVC and allows models to be validated before a controller action is invoked (during model-binding). This approach to validation is more seamless but has several downsides:

Auto validation is not asynchronous: If your validator contains asynchronous rules then your validator will not be able to run. You will receive an exception at runtime if you attempt to use an asynchronous validator with auto-validation.
Auto validation is MVC-only: Auto-validation only works with MVC Controllers and Razor Pages. It does not work with the more modern parts of ASP.NET such as Minimal APIs or Blazor.
Auto validation is hard to debug: The ‘magic’ nature of auto-validation makes it hard to debug/troubleshoot if something goes wrong as so much is done behind the scenes.

We do not generally recommend using auto validation for new projects, but it is still available for legacy implementations.

需要的扩展包

  • FluentValidation.AspNetCore :自动验证需要的包,若不需要自动验证只使用手动验证的话 可以不添加这个包
  • FluentValidation.DependencyInjectionExtensions :自动注册所有的扩展验证类到服务管道

添加服务注册

下面的代码我做了一个类的封装,直接在Program.cs中可以用builder.Services.AddFluentValidationAutoValidation(); 这样来使用

/// <summary>
        /// 添加 FluentValidation 到容器
        /// 自动注册所有验证器
        /// </summary>
        public static void AddFluentValidationSetup(this IServiceCollection services)
        {
            if (services == null) 
                throw new ArgumentNullException(nameof(services));
            if (!Appsettings.app(new string[] { "Startup", "FluentValidation", "Enabled" }).ObjToBool())
                return;
            if (Appsettings.app(new string[] { "Startup", "FluentValidation", "AutoValidation" }).ObjToBool()) // 通过配置文件来控制是否需要使用自动校验
                services.AddFluentValidationAutoValidation(); // 注册这个会 启用自动验证,在控制器前进行实体验证
            services.AddValidatorsFromAssemblyContaining(typeof(IFluentValidation));

        }

IFluentValidation 这个i接口如下:

  /// <summary>
    /// 功 能: 一个空接口,验证类继承该接口,用于批量管道注册
    /// V0.01 2023-2-16 10:23:22 xliu  初版
    /// </summary>
    public interface IFluentValidation
    {
    }

添加两个页面实体

  /// <summary>
    /// 功 能:  用户信息
    /// V0.01 2023-2-13 15:59:21 xliu  初版
    /// </summary>
    public class UserDto
    {
        /// <summary>
        /// 用户id
        /// </summary>
        public string UID { get; set; }

        /// <summary>
        /// 用户类型
        /// </summary>
        public string UType { get; set; }

        /// <summary>
        /// 登录名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 角色id
        /// </summary>
        public string RoleID { get; set; }

        /// <summary>
        /// 角色名称
        /// </summary>
        public string RoleName { get; set; }

        /// <summary>
        /// 权限集
        /// </summary>
        public string Permissions { get; set; }
    }

创建两个 验证是否可以直接注册所有的类到服务

 public class UserDto2
    {
        /// <summary>
        /// 用户id
        /// </summary>
        public string UID { get; set; }

        /// <summary>
        /// 用户类型
        /// </summary>
        public string UType { get; set; }

        /// <summary>
        /// 登录名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 角色id
        /// </summary>
        public string RoleID { get; set; }

        /// <summary>
        /// 角色名称
        /// </summary>
        public string RoleName { get; set; }

        /// <summary>
        /// 权限集
        /// </summary>
        public string Permissions { get; set; }
    }

创建实体验证方法

/// <summary>
    /// 功 能: user请求实体验证
    /// V0.01 2023-2-15 16:56:11 xliu  初版
    /// </summary>
    public class UserValidation: AbstractValidator<UserDto>, IFluentValidation
    {
        public UserValidation() 
        {
            RuleFor(p => p.Name).NotEmpty().WithMessage("用户名不能为空");
        }
    }

    /// <summary>
    /// 功 能: user请求实体验证
    /// V0.01 2023-2-15 16:56:11 xliu  初版
    /// </summary>
    public class UserValidation2: AbstractValidator<UserDto2>, IFluentValidation
    {
        public UserValidation2() 
        {
            RuleFor(p => p.RoleID).NotEmpty().WithMessage("角色ID不能为空");
            RuleFor(p => p.RoleName).NotEmpty();
        }
    }

开始验证

自动验证

注意 自动验证需要注入自动验证那个服务
services.AddFluentValidationAutoValidation();

创建两个控制器
_model 是一个返回实体

 		/// <summary>
        /// 测试 IFluentValidation 效果
        /// </summary>
        /// <param name="userDto2"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateTokenByUser2")]
        public async Task<IActionResult> CreateTokenByUser2(UserDto2 userDto2)
        {
        	// 业务代码
            return BadRequest(_model);
        }
	    [HttpPost]
        [Route("CreateTokenByUser")]
        public async Task<IActionResult> CreateTokenByUser(UserDto userDto)
        {
	        // 业务代码
            return BadRequest(_model);
        }

手动验证

手动验证就需要把那个自动验证的服务注释掉,不然依旧会优先执行自动验证

注入验证器

   		private IValidator<UserDto> _validator;

        public TokenController(IValidator<UserDto> validator)
        {          
            _validator = validator;
        }

		/// <summary>
        /// 根据用户信息创建token
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateTokenByUser")]
        public async Task<IActionResult> CreateTokenByUser(UserDto userDto)
        {
        // 这里就是手动验证代码,将需要验证的实体带到验证器
            ValidationResult result = await _validator.ValidateAsync(userDto);
            if (!result.IsValid)
            {
                _model.Code = 401;
                _model.Msg = result.Errors.ToArray().ToString();
                return Ok(_model);
            }
            
            return Ok(_model);
        }

结果

UserDTO 自动验证

传入一个空的实体

在这里插入图片描述

传入正确的实体

加了创建token的业务
在这里插入图片描述

UserDTO2自动验证

传入一个空的实体

在这里插入图片描述
可以看出利用 IFluentValidation 这个接口做批量注册是成功的

然后再看看手动验证的方式

UserDTO 手动验证

在这里插入图片描述
可以看到,格式是按照我们的返回实体来做的 使得结构可以控制。但是我没有正确的获取 实体错误信息,使得msg有问题。
验证错误信息在 result.Errors 中。

使用可以参照其他的文章会比较好,这里只是简单的做一个介绍和记录。

记录

简单的记录下遇到的坑,看到FluentValidation这个验证 感觉挺好的,想用。但是看到好多文章都是介绍使用 没有一篇在说怎么做批量注入的,都只是按照官网文档做了一个类的注入。想着不合理 应该是批量注入的方法,找了好久 终于在外网看到了一个解决方法:网址
在这里插入图片描述
不过很可惜,这是21年时的方案,现在官方已经废弃这种方式了
变更记录

在这里插入图片描述

可是最新官网介绍,也只有注入一个验证器的示例:
在这里插入图片描述
通过反编译,可以看到是也是通过类似反射的方式拿到哪些使用过这type的类 全部注册到服务。
在这里插入图片描述
在这里插入图片描述
之后就想着,弄一个空接口 让所有的验证器继承并实现该接口,那就可以去找所有实现过该接口的类 那这些就是我需要注册进去的验证器了。

开始打算直接将整个model层的都通过autofac全部注入,想想太大了 太不合理,后又打算通过反射去找符合条件的类 再注册,感觉不好看就没继续。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧校园电子班牌系统

智慧电子班牌区别于传统电子班牌&#xff0c;智慧校园电子班牌系统更加注重老师和学生的沟通交流和及时数据交互。学校为每个教室配置一台智能电子班牌&#xff0c;一般安装于教室门口&#xff0c;用来实时显示学校通知、班级通知&#xff0c;可设置集中分布式管理&#xff0c;…

RSA加解密简单实现

目录 浅谈加解密实现方式 MD5加密 DES加密 AES加密 RSA加密 SSL加密认证 关于RSA加解密实现 简单数据加解密的实现 分块加解密实现 附录 浅谈加解密实现方式 关于数据加解密方式&#xff0c;我们一般分为不可逆加密、对称可逆加密、非对称加密、综合加密应用等&…

魔改并封装 YoloV5 Version7 的 detect.py 成 API接口以供 python 程序使用

文章目录IntroductionSection 1 起因Section 2 魔改的思路Section 3 代码Part 1 参数部分Part 2 识别 APIPart 3 完整的 DetectAPI.pyPart 4 修改 dataloaders.pySection 4 调用ReferenceIntroduction YoloV5 作为 YoloV4 之后的改进型&#xff0c;在算法上做出了优化&#xf…

errgroup 原理简析

golang.org/x/sync/errgroup errgroup提供了一组并行任务中错误采集的方案。 先看注释 Package errgroup provides synchronization, error propagation, and Context cancelation for groups of goroutines working on subtasks of a common task. Group 结构体 // A Gro…

Sphinx : 高性能SQL全文检索引擎

Sphinx是一款基于SQL的高性能全文检索引擎&#xff0c;Sphinx的性能在众多全文检索引擎中也是数一数二的&#xff0c;利用Sphinx&#xff0c;我们可以完成比数据库本身更专业的搜索功能&#xff0c;而且可以有很多针对性的性能优化。 Sphinx的特点 快速创建索引&#xff1a;3分…

Barra模型因子的构建及应用系列三之Momentum因子

一、摘要 在之前的Barra模型系列文章中&#xff0c;我们已经初步讲解、构建了Size因子和Beta因子&#xff0c;并分别创建了对应的单因子策略。通过回测发现&#xff0c;其中Size因子的小市值效应具有很强的收益能力。而本篇文章将在该系列下进一步构建Momentum因子。 二、模型…

90%企业在探索的敏捷开发怎么做?极狐GitLab总结了这些逻辑与流程

本文来自&#xff1a; 彭亮 极狐(GitLab) 高级产品经理 毛超 极狐(GitLab) 研发工程师 极狐(GitLab) 市场部内容团队 “敏捷” 是指能够驾驭变化&#xff0c;保持组织竞争优势的一种能力。自 2001 年《敏捷宣言》以来&#xff0c;敏捷及敏捷开发理念逐渐席卷全球。中国信通院《…

面试已上岸,成功拿到阿里和腾讯的入职offer,Java程序员面经全在这了,希望能帮到你!

前言 一开始的时候简历海投大多数都被拒绝了&#xff0c;后来自己找在腾讯上班的朋友帮忙改了一下简历&#xff0c;果然不一样了大多都能拿到面试机会&#xff0c;当然拿到后也没有那么顺利&#xff0c;面了差不多有十几家公司的样子&#xff0c;大大小小的都有&#xff0c;其中…

C++和QML混合编程_QML发送信号到C++端(信号和槽绑定)

C和QML混合编程_QML发送信号到C端&#xff08;信号和槽绑定&#xff09; 前言&#xff1a; 下面是之前讲解过的三种方法 1、使用Q_INVOKABLE声明一下普通函数&#xff0c;在QML端可以直接调用 2、使用Connections绑定QML的信号和C端的槽函数 3、使用connect绑定QML的信号和C端的…

通俗易懂理解——布隆过滤器

文章目录概述本质优缺点优点&#xff1a;缺点&#xff1a;实际应用解决redis缓存穿透问题&#xff1a;概述 本质 本质&#xff1a;很长的二进制向量&#xff08;数组&#xff09; 主要作用&#xff1a;判断一个数据在这个数组中是否存在&#xff0c;如果不存在为0&#xff0c…

NR PDCP duplication

欢迎关注同名微信公众号“modem协议笔记”。 PDCP duplication 是PDCP 的一个功能&#xff0c;主要是为满足URLLC 场景的可靠性/延迟要求&#xff0c;而产生的一种提高传输可靠性的机制&#xff0c;具体就是在信号状况比较差的情况下&#xff0c;网络侧通过配置PDCP duplicati…

集中式存储和分布式存储

分布式存储是相对于集中式存储来说的&#xff0c;在介绍分布式存储之前&#xff0c;我们先看看什么是集中式存储。不久之前&#xff0c;企业级的存储设备都是集中式存储。所谓集中式存储&#xff0c;从概念上可以看出来是具有集中性的&#xff0c;也就是整个存储是集中在一个系…

Zynq非Video Mixer方案实现视频叠加输出,无需SDK配置,提供工程源码和技术支持

目录1、前言2、Video Mixer的不便之处3、FDMA取代Video Mixer实现视频叠加输出4、Vivado工程详解5、上板调试验证并演示6、福利&#xff1a;工程代码的获取1、前言 关于Zynq使用Video Mixer方案实现视频叠加输出方案请参考点击查看&#xff1a;Video Mixer方案 对于Zynq和Micr…

Elasticsearch:Security API 介绍

在我之前的文章 “Elasticsearch&#xff1a;运用 API 创建 roles 及 users” &#xff0c;我展示了如何使用 Security API 来创建用户及角色来控制访问 Elasticsearch 中的索引。在今天的文章中&#xff0c;我将展示一个使用 Security API 来创建一个用户及角色来访问一个索引…

双指针【灵神基础精讲】

来源0x3f&#xff1a;https://space.bilibili.com/206214 文章目录同向双指针[209. 长度最小的子数组](https://leetcode.cn/problems/minimum-size-subarray-sum/)[713. 乘积小于 K 的子数组](https://leetcode.cn/problems/subarray-product-less-than-k/)[3. 无重复字符的最…

计算机相关专业毕业论文选题推荐

计算机科学以下是我推荐的20个计算机科学专业的本科论文选题&#xff1a;基于机器学习的推荐算法研究与实现基于区块链技术的数字身份认证方案设计与实现基于深度学习的图像识别技术研究与应用基于虚拟现实技术的教育培训平台设计与实现基于物联网技术的智能家居系统研究与开发…

Dubbo与Spring Cloud优缺点分析(文档学习个人理解)

文章目录核心部件1、总体框架1.1 Dubbo 核心部件如下1.2 Spring Cloud 总体架构2、微服务架构核心要素3、通讯协议3.1 Dubbo3.2 Spring Cloud3.3 性能比较4、服务依赖方式4.1 Dubbo4.2 Spring Cloud5、组件运行流程5.1 Dubbo5.2 Dubbo 运行组件5.3 Spring Cloud5.4 Spring Clou…

[数据治理-02]一个例子搞懂元数据、参考数据、主数据、交易数据...的关系

杜威说过“所有知识都是分类”&#xff01;很好理解&#xff0c;分类是认知经济&#xff0c;任何有效分类&#xff0c;都可以极大地节省我们的认知精力。谈到数据就必须做个分类&#xff0c;谈到数据分类可以从多个维度出发&#xff0c;比如按业务维度、这是财务数据、那是人力…

C++ ——多态 下 (图解多态原理、虚函数的再认知)

目录 一、抽象类 1&#xff09;抽象类定义 2&#xff09;抽象类的继承 3&#xff09;抽象类实现多态 4&#xff09;抽象类的好处 二、多态的实现原理 1&#xff09;虚函数的存储方式 2&#xff09;子类中虚函数的存储方式 ① 子类将基类中的虚表原封不动的拷贝到自己的…

【原创】java+swing+mysql教师管理系统设计与实现

教师管理系统主要是方便学校对教师进行管理&#xff0c;本文主要介绍如何使用java的swing窗体控件和mysql数据库去设计一个简单的教师管理系统。 功能分析&#xff1a; 本系统为javaswingmysql的教师管理系统&#xff0c;管理员、教师 功能如下&#xff1a; 管理员&#xff…