在 asp.net 核心中禁用对操作方法的模型验证

Disable a model validation on an action method in asp.net core

我想禁用控制器中特定 Action 方法的模型验证。我有这种情况:

public class SomeDto
{
    public string Name { get; set; }
}

public class SomeDtoValidator : AbstractValidator<SomeDto>, ISomeDtoValidator
{
    public SomeDtoValidator ()
    {
        RuleFor(someDto=> someDto.Name).NotNull().WithMessage("Name property can't be null.");
    }
}

我有 ISomeDtoValidator,因为我以自己的方式注册了所有验证器:

public class Startup
{
    // .... constructor ....

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

        services.RegisterTypes(Configuration)
                .RegisterFluentValidation()
                .RegisterMappingsWithAutomapper()
                .RegisterMvcConfigurations();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
    {
        // ...
    }
}

我在控制器中有这个操作方法:

[DisableFormValueModelBinding]
public async Task<IActionResult> CreateSome(Guid someId, SomeDto someDto)
{
    //..... Manually binding someDto...

    var validator = new SomeValidator();
    validator.Validate(someDto);

    // Doing something more ........

    return Ok();
}       

我禁用了 modelBinding 的 MVC,因为我想在绑定 SomeDto 之前做一些事情,因此,我也不想在 SomeDto 上应用任何验证器。那么,有什么办法可以实现吗??例如,像这样的东西:

[DisableValidator] // Or [DisableValidator(typeof(SomeDtoValidator))] whatever
[DisableFormValueModelBinding]
public async Task<IActionResult> CreateSome(Guid someId, SomeDto someDto)
{
    //..... Manually binding someDto...

    var validator = new SomeValidator();
    validator.Validate(someDto);

    // Doing something more ........

    return Ok();
}   

您可以使用规则集。

参见:https://fluentvalidation.net/start#rulesets

用法:https://fluentvalidation.net/aspnet#validator-customization

public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(customer => customer.Surname).NotEmpty();
        RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
        RuleFor(customer => customer.Address).Length(20, 250);

        RuleSet("Names", () =>
        {
            RuleFor(x => x.Surname).NotNull();
            RuleFor(x => x.Forename).NotNull();
        });

        RuleSet("Empty", () =>
        {
        });
    }
}

测试代码:

        Customer customer = new Customer();
        var validator = new CustomerValidator();
        var validationResult = validator.Validate(customer, ruleSet: "Names");
        // 2 errors: Surname and Forname
        validationResult = validator.Validate(customer, ruleSet: "Empty");
        // no errors

您可以在控制器中配置规则集:

public ActionResult SaveNoValidate([CustomizeValidator(RuleSet="Empty")] Customer customer) {
// ...
}

public ActionResult SaveValidateNames([CustomizeValidator(RuleSet="Names")] Customer customer ) {
// ...
}

我在@Alexey.Petriashev 的帮助下达到了我的目标,只在验证器中放置了一个规则集。当管道调用验证器时,它不会进行验证,因为管道调用没有 RuleSet。下面是我如何解决问题的示例:

public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleSet("Manually", () =>
        {
            RuleFor(x => x.Surname).NotNull();
            RuleFor(x => x.Forename).NotNull();
        });
    }
}

public ActionResult ActionWithoutValidationExecuted(Customer customer) 
{
    //..... Manually binding customer...

    var validator = new CustomerValidator();
    var validResult = validator.Validate(customer, ruleSet: "Manually");

    // Doing something more ........

    return Ok();
}

您可以通过将以下属性添加到操作方法参数来跳过验证:

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

此处的文档对此进行了描述: https://docs.fluentvalidation.net/en/latest/aspnet.html#validator-customization