0

    .Net Core 使用 FluentValidation

    2023.06.10 | admin | 151次围观

    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, CustomerValidator>();

    自动注册验证器

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

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

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

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

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

    services.AddMvc().AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining(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 字典中的前缀。

    .Net Core 使用 FluentValidation

    验证程序自定义

    您可以使用 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());
    }

    程序员灯塔

    转载请注明原文链接:.Net Core 使用 FluentValidation

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论