zoukankan      html  css  js  c++  java
  • 【翻译】asp.net core中使用FluentValidation来进行模型验证

    asp.net core中使用FluentValidation

    FluentValidation 可以集成到asp.net core中。一旦启用,MVC会在通过模型绑定将参数传入控制器的方法上时使用FluentValidation 。

    你可以通过Install-Package FluentValidation.AspNetCore来引入相应的Nuget包。

    安装后,你需要在StartUp类中的ConfigureService方法中配置:

    public void ConfigureServices(IServiceCollection services) {
        services.AddMvc(setup => {
          //...mvc setup...
        }).AddFluentValidation();
    }

    同时,你需要在ServiceCollection中注入你的验证规则:

    public void ConfigureServices(IServiceCollection services) {
        services.AddMvc(setup => {
          //...mvc setup...
        }).AddFluentValidation();
    
        services.AddTransient<IValidator<Person>, PersonValidator>();
        //etc
    }

    上面那种方法一次只注入一个,你可以通过下面的方法将所有验证规则注入:

    services.AddMvc()
      .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<PersonValidator>());

    下面假设一个将要验证Person类的验证规则:

    public class Person {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public int Age { get; set; }
    }
    
    public class PersonValidator : AbstractValidator<Person> {
        public PersonValidator() {
            RuleFor(x => x.Id).NotNull();
            RuleFor(x => x.Name).Length(0, 10);
            RuleFor(x => x.Email).EmailAddress();
            RuleFor(x => x.Age).InclusiveBetween(18, 60);
        }
    }

    我们可以在控制器和关联的视图中使用Person类:

    public class PeopleController : Controller {
        public ActionResult Create() {
            return View();
        }
    
        [HttpPost]
        public IActionResult Create(Person person) {
    
            if(! ModelState.IsValid) { // re-render the view when validation failed.
                return View("Create", person);
            }
    
            Save(person); //Save the person to the database, or some other logic
    
            TempData["notice"] = "Person successfully created";
            return RedirectToAction("Index");
    
        }
    }

    下面是对应的视图:

    @model Person
    
    <div asp-validation-summary="ModelOnly"></div>
    
    <form asp-action="Create">
      Id: <input asp-for="Id" /> <span asp-validation-for="Id"></span>
      <br />
      Name: <input asp-for="Name" /> <span asp-validation-for="Name"></span>
      <br />
      Email: <input asp-for="Email" /> <span asp-validation-for="Email"></span>
      <br />
      Age: <input asp-for="Age" /> <span asp-validation-for="Age"></span>
    
      <br /><br />
      <input type="submit" value="submtit" />
    </form>

    现在当你提交表单,模型绑定组件会使用PersonValidator,并且将验证结果放到ModelState中。

    当使用这种自动集成来执行验证器时,对于高级用户来说,RootContextData包含一个名为InvokedByMvc的条目,它的值设置为true,可以在定制确认器中使用它来判断一个验证器是由MVC自动调用的,还是手动的。

    和asp.net core内置的验证的兼容性

    默认情况下,当FluentValidation执行完成后其它的模型验证也有机会执行。这意味着你可以将FluentValidation和asp.net core内置的验证混用。

    如果你想制止这种行为,你可以这样配置:

    services.AddMvc().AddFluentValidation(fv => {
     fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
    });

    设置RunDefaultMvcValidationAfterFluentValidationExecutes为false意味着对IValidatableObject的支持也被禁止了。

    隐式的 vs显式的对属性的属性的验证

    当验证一个复杂类型的对象时,你必须显式的通过SetValidator方法为属性指定一个验证程序。

    当运行一个ASP.NET MVC应用程序,也可以选择性地为子属性启用隐式验证。当启用此功能时,无需使用SetValidator指定子验证器,MVC的验证基础设施将递归地尝试为每个属性自动查找验证器。这可以通过将隐式的的validatechild属性设置为true来实现:

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

    需要注意的是如果你开启了这个功能,那你就不要再用SetValidator来为属性的属性指定一个验证器,否则会验证两遍。

    客户端验证

    FluentValidation 是一个服务端的框架。并不会提供任何客户端的验证。但是,他可以为生成的html提供元数据,这些元数据可以被前端的框架诸如jquery validation所使用。比如asp.net core的验证特性(attribute)就是这个干的。

    但不是所有的内置验证规则都能被客户端使用,能够被客户端使用的如下:

    • NotNull/NotEmpty
    • Matches (regex)
    • InclusiveBetween (range)
    • CreditCard
    • Email
    • EqualTo (cross-property equality comparison)
    • MaxLength
    • MinLength
    • Length

    手动验证

    在一些情况下你想要手动的验证一些对象,在这种情况下,验证的结果能被放入ModelState的Dictionary里面:

    public ActionResult DoSomething() {
      var customer = new Customer();
      var validator = new CustomerValidator();
      var results = validator.Validate(customer);
    
      results.AddToModelState(ModelState, null);
      return View();
    }
    AddToModelState是一个扩展方法需要引入FluentValidation 命名空间,第二个参数是一个可选参数,会作为属性的名称的前缀,比如AddToModelState(ModelState, “Foo”),会生成Foo.Id或Foo.Name而不是Id或Name

    定制验证

    使用这种自动集成的缺点是,你不能直接访问验证器,这意味着与手动运行验证器相比,你对验证过程的控制没有那么多。你可以使用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" });

    你还可以使用Customizeevalidatorattribute来跳过特定类型的验证。如果你需要手动验证类型(例如,如果您想执行异步验证,那么您需要手动实例化验证器,并调用ValidateAsync,因为MVC的验证管道不是异步的)。

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

    验证拦截器

    你可以进一步的通过一个拦截器来定制这个过程。这个拦截器需要实现FluentValidaiton.MVC命名空间下的IValidatorInterceptor 接口。

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

    这个接口有两个方法:BeforeMvcValidation 和AfterMvcValidation。

    太累了,明天继续把。。。

  • 相关阅读:
    Python全栈day19(函数补充)
    Python全栈day18(三元运算,列表解析,生成器表达式)
    Python全栈day18(迭代器协议和for循环工作机制)
    KVM虚拟化
    Python使用函数实现把字符串转换成整数
    MySQL备份1356错误提示修复办法
    Python全栈day17(文件处理)
    CentOS添加PHP至环境变量
    CentOS7.2编译配置LNMP环境(MySQL5.7.20,PHP7.0.24)
    php查询mysql数据库 查询条件替中文字符串变量时无法查询
  • 原文地址:https://www.cnblogs.com/pangjianxin/p/9332958.html
Copyright © 2011-2022 走看看