.Net Core 使用 FluentValidation

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

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

安装完成后,您须要经过在 AddFluentValidation 方法在 Startup 类中的 ConfigureServices 方法中注册服务。函数

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

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

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

自动注册验证器

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

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验证器:blog

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());
}
相关文章
相关标签/搜索