.NET Core中的验证组件FluentValidation的实战分享

.NET Core中的验证组件FluentValidation的实战分享

今天有人问我能不能出一篇FluentValidation的教程,刚好今天在实现我们的.NET Core实战项目之CMS的修改密码部分的功能中有用到FluentValidation,所以就以修改用户密码为实例来为大家进行一下ASP.NET Core中的验证组件FluentValidation的实战分享,希望能对大家有所帮助!由于本文以.NET Core实战项目之CMS中的项目为例,因此此篇文章会收录到系列教程的目录中。

本篇文章已经收纳入《.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划》另附上.NET Core实战项目交流群:637326624 有兴趣的朋友可以共同交流技术经验。
作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/10397393.html

写在前面

开始之前还是有必要为大家科普一下FluentValidation的概念,它是一个非常流行的用来构建强类型验证规则的.NET库。而且它对ASP.NETCore支持十分友好,可以很方便的进行集成使用,集成后我们可以很方便的对数据模型进行强验证。
另外附上GitHub地址:https://github.com/JeremySkinner/FluentValidation 有近四千多的Star说明受众还是挺多的
官方文档:https://fluentvalidation.net/
为什么要使用它呢?
因为它足够简单,而且功能强大,可以很方便的来为我们建立起强大的实体验证功能!另外社区也挺活跃,作者也在持续维护中。那么怎么使用它呢?下面我们就通过修改密码的实例来进行讲解!

FluentValidation使用

开始使用之前我们先构思一下密码修改需要进行的验证规则:

  • 密码强度验证
  • 旧密码是否跟数据库中的一样
  • 新密码不能跟旧密码一样
  • 重复密码需要跟新密码一样
  • 当前页面用户必须登录,用户ID必须大于0

好了,假设我们需要实现上述的功能验证,怎么来进行实现呢?当然我们可以通过.net core中的DataAnnoations 进行实现,但是今天我们要使用FluentValidation来实现一番。下面是具体步骤!

使用

  1. 首先当然是添加FluentValidation.AspNetCore Nuget包了:

    Install-Package FluentValidation.AspNetCore
  2. 安装后,需要在应用程序的Startup中的ConfigureServices方法中调用AddFluentValidation内的扩展方法。(这里需要using FluentValidation.AspNetCore),需要注意的是这个扩展方法必须在调用AddMvc 之后进行调用。如下所示:

    1550485204696

    注意:

    1. AddFluentValidation方法必须在AddMvc之后进行调用

    2. 我在AddFluentValidation中加入了两个配置,都有注释你应该能看懂。

  3. 下面根据我们步骤开始之前的分析创建如下的修改密码的视图模型

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:修改密码实体                                                    
    *│ 作    者:yilezhu                                             
    *│ 版    本:1.0                                                 
    *│ 创建时间:2019/1/22 12:50:54                             
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空间: Czar.Cms.ViewModels.Manager                                   
    *│ 类    名: ChangePasswordModel                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Czar.Cms.ViewModels
    {
        public class ChangePasswordModel
        {
            /// <summary>
            /// 当前管理员主键
            /// </summary>
            public int Id { get; set; }
            /// <summary>
            /// 旧密码
            /// </summary>
            public string OldPassword { get; set; }
            /// <summary>
            /// 新密码
            /// </summary>
            public string NewPassword { get; set; }
            /// <summary>
            /// 重复密码
            /// </summary>
            public string NewPasswordRe { get; set; }
        }
    }
    
  4. 为这个视图模型创建一个校验类,用来添加我们上面列出来的校验规则,如下所示:

    using Czar.Cms.ViewModels;
    using FluentValidation;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Czar.Cms.Core.Extensions;
    
    namespace Czar.Cms.Admin.Validation
    {
        public class ChangePasswordModelValidation : AbstractValidator<ChangePasswordModel>
        {
            public ChangePasswordModelValidation()
            {
                CascadeMode = CascadeMode.StopOnFirstFailure;
                RuleFor(x => x.Id).NotNull().GreaterThan(0).WithMessage("用户信息获取异常");
                RuleFor(x => x.OldPassword).NotEmpty().Length(4, 32).WithMessage("旧密码不能为空且长度必须符合规则");
                RuleFor(x => x.NewPassword).NotEmpty().Length(4, 32).WithMessage("新密码不能为空且长度必须符合规则")
                    .Must(NewNotEqualsOld).WithMessage("新密码不能跟旧密码一样");
                RuleFor(x => x.NewPasswordRe).NotEmpty().WithMessage("重复密码不能为空").Must(ReEqualsNew).WithMessage("重复密码必须跟新密码一样");
    
            }
    
            /// <summary>
            /// 判断新旧密码是否一样
            /// </summary>
            /// <param name="model">实体对象</param>
            /// <param name="newPwd">新密码</param>
            /// <returns>结果</returns>
            private bool NewNotEqualsOld(ChangePasswordModel model , string newPwd)
            {
                return model.OldPassword!=newPwd;
            }
    
            /// <summary>
            /// 判断新密码与重复密码是否一样
            /// </summary>
            /// <param name="model"></param>
            /// <param name="newPwdRe"></param>
            /// <returns></returns>
            private bool ReEqualsNew(ChangePasswordModel model, string newPwdRe)
            {
                return model.NewPassword == newPwdRe;
            }
        }
    }
    

    注:上述代码应该很好理解吧,为了防止有初学者,所以这里再废话一下:

    1. 为每个需要验证的实体创建一个这样的类,如我们要验证的实体是ChangePasswordModel 因此我们创建一个ChangePasswordModelValidation
    2. 验证类需要继承AbstractValidator<T> 如:ChangePasswordModelValidation : AbstractValidator
    3. 在构造函数中写验证规则
    4. RuleFor()是为当前实体的某一个属性添加验证,如:RuleFor(x => x.Id).NotNull().GreaterThan(0) 就是验证这个实体的Id 这个字段不能为空,而且必须大于0.后面的WithMessage 就是如果前面校验失败就返回的错误信息
    5. 如果要添加自定义的验证,如:判断新密码是否与旧密码一致,这里就先定义这个校验方法,如:NewNotEqualsOld 这个方法我们自定义的,然后再RuleFor().Must(NewNotEqualsOld) 即可应用
  5. 在我们的修改密码功能提交的时候应用我们的验证,只需要正常的使用即可,如:

    1550487024704

    如上所示,该怎么用还怎么用,然后再继续模型校验的时候会自动应用我们的规则。如果我们定义的规则校验失败的话,这时候ModelState.IsValid 会返回false 这时候我们就可以把错误信息通过我们在BaseController 中自定义的ToErrorString(ModelState,"||"); 方法打印出来。

功能验证

这里我们先把前台的验证规则都给去掉,然后我们刚开始设计的几个规则的校验吧!

密码强度验证

这里我们简单的继续密码长度的校验,如长度满足在:4-32位 ,我们对应的FluentValidation 的验证规则为RuleFor(x => x.OldPassword).NotEmpty().Length(4, 32) 这里还进行了非空的校验。如下图所示:

1550487595306

旧密码是否跟数据库中的一样

这个校验我是在密码提交后进行的校验,没有放在FluentValidation中,所以这块只展示测试效果图吧

1550487708209

新密码不能跟旧密码一样

这部分我们对应的FluentValidation中的验证规则是:新增自定义方法,然后调用RuleFor().Must(NewNotEqualsOld).WithMessage("新密码不能跟旧密码一样")
效果如下所示:

1550487850978

重复密码需要跟新密码一样

这部分我们对应的FluentValidation中的验证规则是:新增自定义方法,然后调用RuleFor().Must(ReEqualsNew).WithMessage("重复密码必须跟新密码一样")
效果如下所示:

当前页面用户必须登录,用户ID必须大于0

这部分我们对应的FluentValidation中的验证规则是:RuleFor()..NotNull().GreaterThan(0)
效果如下所示:

1550488194952

源码地址

这个系列教程的源码我会开放在GitHub以及码云上,有兴趣的朋友可以下载查看!觉得不错的欢迎Star
GitHub:https://github.com/yilezhu/Czar.Cms
码云:https://gitee.com/yilezhu/Czar.Cms
如果你觉得这个系列对您有所帮助的话,欢迎以各种方式进行赞助,当然给个Star支持下也是可以滴!另外一种最简单粗暴的方式就是下面这种直接关注我们的公众号了:

img

总结

本篇文章,我通过用户密码修改的实例来为大家详细讲解了FluentValidation的使用以及注意事项,希望能对大家有所帮助。因为本篇文章使用我们系列教程中的实例,所以本篇文章会收录至系列教程的目录中!本篇文章用了两个番茄时间才完成。

posted @ 2019-02-19 07:47 依乐祝 阅读( ...) 评论( ...) 编辑 收藏
<think>好的,我需要帮助用户找到在ASP.NET Core8.0Web API中使用FluentValidation进行异步验证的教程。首先,我要回忆一下用户之前提到的引用内容,看看有没有相关的信息。用户提到了.csproj文件、CRUD操作、HTTP状态码以及Program.cs的配置,这些可能和验证有关联,但需要更具体的信息。用户的问题是关于FluentValidation的异步验证,我需要确保回答覆盖以下几个关键点:安装配置、创建验证器、异步验证方法、注册服务、处理错误响应,以及可能的性能优化。同时,要参考用户提到的引用,比如在Program.cs中配置中间件,可能需要注册验证服务,而HTTP状态码的部分可以用于处理验证失败的响应。首先,安装FluentValidation的NuGet包,用户可能需要在.csproj中添加包引用。然后创建自定义验证器类,继承自AbstractValidator,并实现异步规则。例如,使用MustAsync方法进行异步验证,比如检查用户名是否已存在,这可能需要调用数据库,所以异步操作很重要。 接下来,在Program.cs中注册FluentValidation的服务,确保验证器被正确添加到DI容器中。用户之前提到Program.cs中的构造器和中间件配置,这里需要添加services.AddValidators()之类的代码。然后,在控制器动作中,使用自动验证或者手动触发验证。如果自动验证,需要配置ApiController属性,或者使用ModelState.IsValid来检查。验证失败时,返回合适的HTTP状态码,比如400Bad Request,用户之前引用的例子中有返回CreatedAtAction和Ok,这里需要返回错误信息,可能用BadRequest(ModelState)。还需要考虑异步验证的性能,比如数据库查询的优化,避免重复验证。此外,生成相关问题,可能涉及自定义错误消息、集成Swagger文档、单元测试方法等。确保所有步骤都有代码示例,比如验证器类、控制器的POST方法,以及Program.cs的配置。同时,引用用户提到的引用内容,比如在Program.cs中添加验证服务,或者在返回结果时使用正确的HTTP状态码,如引用[3]中的例子。最后,检查是否所有行内数学表达式都正确使用$...$格式,独立公式是否用$$...$$,但在这个问题中可能涉及较少数学公式,更多是代码和配置。确保回答结构清晰,分步骤说明,并生成相关问题。</think>### ASP.NET Core 8.0 Web API中使用FluentValidation进行异步验证的指南 #### 1. **安装与基础配置** - **步骤1**:通过NuGet安装`FluentValidation.AspNetCore`和`FluentValidation.DependencyInjectionExtensions`包 ```xml <!-- .csproj文件引用示例 --> <PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" /> ``` - **步骤2**:在`Program.cs`中注册FluentValidation服务 ```csharp builder.Services.AddControllers() .AddFluentValidation(fv => { fv.RegisterValidatorsFromAssemblyContaining<Startup>(); fv.AutomaticValidationEnabled = true; // 启用自动验证 }); ``` 此配置与中间件集成,确保验证在模型绑定阶段自动触发[^4]。 #### 2. **实现异步验证器** - **示例**:创建异步用户名唯一性验证器 ```csharp public class UserValidator : AbstractValidator<User> { private readonly IUserRepository _repository; public UserValidator(IUserRepository repository) { _repository = repository; RuleFor(x => x.Username) .MustAsync(async (username, cancellationToken) => !await _repository.ExistsAsync(username)) .WithMessage("用户名已存在"); } } ``` 使用`MustAsync`方法定义异步验证规则,适用于数据库查询等I/O操作。 #### 3. **控制器层集成** - **自动验证**:在控制器动作中依赖`ApiController`特性自动返回400错误 ```csharp [HttpPost] public async Task<IActionResult> CreateUser(User user) { if (!ModelState.IsValid) return BadRequest(ModelState); // 自动触发验证结果[^3] var result = await _service.CreateAsync(user); return CreatedAtAction(nameof(GetUser), new { id = result.Id }, result); } ``` #### 4. **自定义异步验证场景** - **跨字段异步验证**:实现多字段组合验证 ```csharp RuleFor(x => x.Email) .MustAsync(async (user, email, context, cancellationToken) => await IsEmailUniqueAsync(user.Id, email)) .When(x => x.Id == 0); // 仅对新用户生效 ``` #### 5. **性能优化与注意事项** - **缓存策略**:对高频验证规则(如字典数据)添加缓存机制 - **并行处理**:使用`WhenAsync`条件判断避免不必要的异步调用 - **日志记录**:通过注入`ILogger`记录验证失败详情 #### 6. **错误响应标准化** - **统一格式**:通过过滤器定制错误响应结构 ```csharp options.Filters.Add(new ValidationFilter()); // 全局注册 public class ValidationFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(...) { if (!context.ModelState.IsValid) { var errors = context.ModelState.ToErrorDictionary(); context.Result = new BadRequestObjectResult(new { Code = 400, Errors = errors }); } } } ``` 此方式可生成类似`{ "Code":400, "Errors": { "Username": ["已存在"] } }`的结构化响应[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值