.Net Core 使用FluentValidation

FluentValidation 支持与 ASP.NET Core 2.1 或3.1集成(建议使用3.1)。启用后,MVC将使用 FluentValidation 来验证由模型绑定基础结构传递到控制器操作中的对象。

要启用MVC集成,您需要 FluentValidation.AspNetCore 通过安装适当的NuGet软件包来添加对程序集的引用。

安装完成后,您需要通过在 AddFluentValidation 方法在 Startup 类中的 ConfigureServices 方法中注册服务。

public void ConfigureServices(IServiceCollection services)
{              
  services.AddMvc().AddFluentValidation().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

为了使验证生效还需要再 ConfigureServices 中依赖注入我们的验证器。

services.AddTransient<IValidator<Customer>, CustomerValidator>();

自动注册验证器

不过这样一个个注册太麻烦了,所以有一个批量注册的方法 RegisterValidatorsFromAssemblyContaining 通过这个方法可以注册特定程序集中的所有的验证器。这将自动查找从其继承 AbstractValidator 并在容器中注册的所有公共非抽象类型(不支持开放的泛型)。如下所示创建一个验证器和一个验证器接口,相应的类我就不创建了。

public class CustomerValidator : AbstractValidator<Customer> , IValidator
{
  public CustomerValidator()
  {
    RuleFor(t => t.Name).NotEmpty();
  }
}
public interface IValidator{}

之后在 Startup 类中的 ConfigureServices 方法中使用 RegisterValidatorsFromAssemblyContaining 注册 IValidator 接口,这样所有继承 IValidator 和 AbstractValidator 的验证器就会全部自动注册了。

services.AddMvc().AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<IValidator>()).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

自动注册的验证器是以 Transient 的形式注册的而不是 Singleton 。如果您不想注册特定的验证器类型,则可以使用过滤器回调将其排除,如下所示就排除了CustomerValidator验证器:

services.AddMvc().AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<IValidator>(discoveredType => discoveredType.ValidatorType != typeof(CustomerValidator))).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

在控制器中使用验证器

直接用原来的 ModelState.IsValid 就可以了。

public IActionResult Create(Customer customer)
{
  customer = new Customer();
  CustomerValidator validationRules = new CustomerValidator();
  if (!ModelState.IsValid)
    return Content("失败了");
  return View();
}

运行应用程序时,还可以选择对子属性启用隐式验证。启用此功能后,无需使用来指定子验证器 SetValidator,MVC的验证基础结构将递归地尝试自动为每个属性查找验证器。可以通过设置 ImplicitlyValidateChildProperties 为true来完成:

services.AddMvc().AddFluentValidation(fv => {
 fv.ImplicitlyValidateChildProperties = true;
});

请注意,如果启用此行为,则不应将其 SetValidator 用于子属性,否则验证程序将执行两次。

手动验证

有时您可能需要手动验证 MVC 项目中的对象,在这种情况下, 我们可以将验证结果复制到 MVC 的 ModelState 字典中,便可用于前端错误提示。

public ActionResult DoSomething() {
  var customer = new Customer();
  var validator = new CustomerValidator();
  var results = validator.Validate(customer);

  results.AddToModelState(ModelState, null);
  return View();
}

AddToModelState 方法是作为扩展方法实现的, 需要引用 FluentValidation 命名空间,请注意, 第二个参数是可选的模型名称前缀, 该参数可设置对象属性在 ModelState 字典中的前缀。

验证程序自定义

您可以使用 CustomizeValidatorAttribute 为模型指定验证程序,也支持为验证器指定规则集。

public ActionResult Save([CustomizeValidator(RuleSet="MyRuleset")] Customer cust) {
  // ...
}

这相当于为验证指定规则集,等同于将规则集传递给验证程序:

var validator = new CustomerValidator();
var customer = new Customer();
var result = validator.Validate(customer, ruleSet: "MyRuleset");

该属性还可用于调用单个属性的验证:

public ActionResult Save([CustomizeValidator(Properties="Surname,Forename")] Customer cust) {
  // ...
}

这相当于对验证程序指定特定属性,其它属性将不被验证:

var validator = new CustomerValidator();
var customer = new Customer();
var result = validator.Validate(customer, properties: new[] { "Surname", "Forename" });

也可以使用 CustomizeValidatorAttribute 特性跳过某些类型的验证。

public ActionResult Save([CustomizeValidator(Skip=true)] Customer cust) {
  // ...
}

验证器拦截器

您可以使用拦截器进一步自定义验证过程,拦截器必须实现 FluentValidation.Mvc 命名空间中的 IValidatorInterceptor 接口:

public interface IValidatorInterceptor    {
  ValidationContext BeforeMvcValidation(ControllerContext controllerContext, ValidationContext validationContext);
  ValidationResult AfterMvcValidation(ControllerContext controllerContext, ValidationContext validationContext, ValidationResult result);
}

此接口有两个方法:BeforeMvcValidation 和 AfterMvcValidation,分别可拦截验证前和验证后的过程。除了在验证程序类中直接实现此接口外, 我们还可以在外部实现该接口, 通过 CustomizeValidatorAttribute 特性指定拦截器:

public ActionResult Save([CustomizeValidator(Interceptor=typeof(MyCustomerInterceptor))] Customer cust) {
 //...
}

在这种情况下, 拦截器必须是一个实现 IValidatorInterceptor 接口,并具有公共无参数构造函数的类。请注意, 拦截器是高级方案,大多数情况下, 您可能不需要使用拦截器, 但如果需要, 可以选择它。

为客户端指定规则集

默认情况下 FluentValidation 不会为客户端生成基于规则集的验证代码, 但您可以通过 RuleSetForClientSideMessagesAttribute 为客户端指定规则集。

[RuleSetForClientSideMessages("MyRuleset")]
public ActionResult Index() {
   return View(new PersonViewModel());
}

也可以在控制器中使用 SetRulesetForClientsideMessages 扩展方法 (需要引用 FluentValidation 命名空间)为客户端指定规则集。

public ActionResult Index() {
   ControllerContext.SetRulesetForClientsideMessages("MyRuleset");
   return View(new PersonViewModel());
}

原文出处:博客园【xwc1996】

原文链接:https://www.cnblogs.com/xwc1996/p/13966070.html

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论