ASP.NET Core 中的请求数据校验

一..NET Core 内置数据校验的不足

无论是通过在属性上标注校验规则 Attribute的方式,还是实现IValidatableObject接

口的方式,我们的校验规则都是和模型类耦合在一起的,这违反了面向对象的“单一职责原则”。

NET Core中内置的校验规则不够多,很多常用的校验需求都需要我们编写意定义,验规则。

二. FluentValidation

上边我们提到了.NET Core 中内置数据校验机制的不足,这里推推荐一个优秀的数据校验框架--FluentValidation,它可以让我们用类似于EF Core 中Fluent API的方式进行校验规则的配置,也就是我们可以把对模型类的校验放到单独的校验类 FluentValidation 可以用于控制台、WPF、ASPNET Core 等各种NET目中。

三.FluentValidation的基本使用

第1步,在项目中安装 NuGet包FluentValidation.AspNetCore.

第2步,在 Program.cs 中添加注册相关服务的代码

1. bullder.Services.addfiuentValidation(fv =>{ |

2.Assembly assembly = Assembly.GetExecutingAssembly();

3. fv.RegiaterValidatorsFromAssenbly(assembly);

4 });

RegisterValidatorsFromAssembly方法用于把指定程序集中所有实现了 IValidator 接口的数据校验类注册到依赖注入容器中,因为这个例子中只有一个项目,所有的数据校验类也都写这个项目中,所以我们用Assembly.GetExecutingAssembly获取入口项目的程序集。在实际的项目中,数据校验类可能会位于多个程序集中,我们可以调用 RegisterValidatorsFromAssemblies米指定这些程序集进行注册。

第3步,编写一个模型类 Login2Request,

Login2Request 类

public record Login2Request(string Email, string Pansword, atring Paasmord2);

可以看到,这里的Login2Request 类只是一个普通的C#类,没有标注任何的 Altribuk成者实现任何的接口,这个类的唯一责任就是传递数据

第4步,编写一个维承自 AbstractValidator 的数据校验类

Login2RequestValidator类

1 public class Login2RequestValidator: AbatraceValidator<Login2Request>

2{

3public Login2RequestValidator()

4{

5RuleFor(x=>x.Email).NotNull().EmailAnddress ()

6 .Must(v=>v.EndsWith("@qq.com") || v.EndsWith("@163.com"))

7 . WithMessage(“只支持QQ和 163 邮箱");

8 RuleFor(x =>xPaseword),Hot0a11 1) .Lengtn(3, 10)

9 .WithMessage("密码长度必介于3到10 之间”)

10 .Equal(x => x.Passwbrd2).withMessage("两次密码必法一致”)

11 }

12 }

数据校验类一般继承自AbstractValidator,AbstractValidator类是一个泛型类,我们需要通过泛型参数指定这个数据校验类对哪个类进行校验,校验规则写到校验类的构造方法中;我们通过 RuleFor 来指定要对哪个属性进行校验,然后使用NotNull(非空)EmailAddress(邮箱地址)、Length(字符串长度)等内置方法来编写校验规则:多个校验规则可以采用链式调用的写法:每个需要校验的属性对应一组 RuleFor 调用,上面的第 5~7 行代码用于对 Emaii 性进行校验,而第 8~10 行代码用于对 Password 属性进行校验。

FluentVabdation 中内置了丰富的校验规则,如果想编写自定义校验规别,我们可以在 Must方法中编写,如第6行代码所示。

FluentValidation 内置的校验规则有默认的报错信息,我们也可以通过WithMessage方法自定义报错信息,WithMessage方法设置的报错信息只作用于它之前的那个校验规则,如第7行代码和第 10 行代码所示。

第5步,我们编写一个操作方法,用 Login2Request 作为参数。然后我们在客户端向这个操作方法对应的路径发送非法的数据,服务器端响应的报文如图所示。

可以看到,使用 FluentValidation 以后,我们可以把数据校验的规则写到单独的数据校验类中,这样模型类和数据校验类各司其职,符合“单一职责原则”,而且在 FluentVialiciation 中编写自定义校验代码也更加简单。FlucntValidation 和NET Core内置的校验方式是可以共存的也就是我们可以一部分校验规则用 FluentVabdation 写,另一部分校验规则用:NET Core 内置的校验方式写,不过为了代码的统一,建议不要混用这两者。

四. FluentValidation中注入服务

在编写数据校验代码的时候,有时候我们需要调用依赖注入容器中的服务, FlucntValidation中的数据校验类是通过依赖注入容器实例化的,因此我们同样可以通过构造方法来向数据校验类中注入服务。

实例

数据库的一张表中记录着系统中已有的用户名,密码等信息,用户表的实体类为User,我们通过TestDbContex读取数据

下面来实现在登录的时候检查用户名是否存在的校验类。

定文一个类Login]Requcs,这个类包含 UserName(用户名),Passwond(密码)两个属

性。

然后,我们再编写一个对 Login3Request 进行校验的类,

1public class Login3RequestValidator:AbstractValidator<Login3Request >

2{

3publisLogin3RequestValidator(TestDbcontext dbCtx)

4{

5RuleFor(x => x.UserName).NotNull()

6 .Must(name=>dbCtx.User.Any(u=>u.UserName==name))

7 .withMessage(c=>$"用户名{c.UserName}不存在“);

8 }

9 }

可以看到,我们通过构造方法注入了 TestDbContext,并且在第6行代码的Must方法中使用了TestDbContext服务检查用户名是否存在。值得注意的是,我们在第7行代码的 withMessage方法中还可以用 Lambda表达式的形式使用模型类中的属性对报错信息进行格式化。

由于异步代码通常能给系统带来更好的吞吐量,因此我们编写代码的原则是“能用异步妈就不要用同步代码”。第6行代码使用同步的 Any方法判断用户名是否存在,而EFCom有一个AnyAsync方法,它是异步版本的Any方法。在FluentValidation 中我们可以用MustAsync和 AnyAsync 来编写异步校验规则,

异步校验规则代码

5RuleFor(x => x.UserName).NotNull()

6 .MustAsync(name,_ )=>dbCtx.Users.AnyAsync(u=>u.UserName==name))

7 .withMessage(c=>$"用户名{c.UserName}不存在“);

猜你喜欢

转载自blog.csdn.net/qq_71012549/article/details/128680178
今日推荐