FluentValidation在输入属性为对象列表时不验证List<string>。

huangapple go评论83阅读模式
英文:

FluentValidation does not validate List<string> when input property is List of objects

问题

I have the following model (simplified for brevity):

{
    public List&lt;string&gt; Values { get; set; }
}

Then my ApiController as following:

public AdvancedFilter Test(List&lt;AdvancedFilter&gt; filters)
{
    return filters.First();
}

Now my Validator looks as following:

{
    public AdvancedFilterValidator()
    {
        RuleFor(x =&gt; x.Values).NotEmpty().ForEach(x =&gt; x.MinimumLength(20));
        //RuleForEach(x =&gt; x.Values).MinimumLength(20); (tried both approaches, none of them worked for me)
    }
}

When I try to call my endpoint with invalid payload such as

[
  {
     &quot;values&quot;:[&quot;test&quot;]
  }
]

It does not throw a Validation exception back at me. Interestingly enough, when I change my controller to accept just a single object like this, the Fluent Validation suddenly kicks in as expected.

[HttpPost(&quot;test&quot;)]
public AdvancedFilter Test(AdvancedFilter filters)
{
    return filters;
}

I am using ASP Net Core v 6 with FluentValidation.AspNetCore version "11.3.0" (latest).

Bonus question:
My end goal with this validation is to ensure that all input values are numbers (even though they are strings, for certain cases I need to make sure they are int). The expanded model would shed more light on it (still simplified):

{
    public AdvancedFilterColumn Column { get; set; }
    public List&lt;string&gt; Values { get; set; }
}

public class AdvancedFilterValidator : AbstractValidator&lt;AdvancedFilter&gt;
{
    public AdvancedFilterValidator()
    {
        When(x =&gt; x.Column == AdvancedFilterColumn.Jurisdiction, () =&gt;
        {
            RuleForEach(x =&gt; x.Values).Must(x =&gt; int.TryParse(x, out _));
        });
    }
}

As you can see, for a specific case when Column is Jurisdiction, I need to make sure that passed-in values are all numbers. I believe the validation rule is written correctly, yet I cannot test it (due to the above-mentioned problem).

Any help in respect to this matter would be highly appreciated.

英文:

I have the following model (simplified for brevity)

public class AdvancedFilter
{
    public List&lt;string&gt; Values { get; set; }
}

Then my ApiController as following

    [HttpPost(&quot;test&quot;)]
    public AdvancedFilter Test(List&lt;AdvancedFilter&gt; filters)
    {
        return filters.First();
    }

Now my Validator looks as following

public class AdvancedFilterValidator : AbstractValidator&lt;AdvancedFilter&gt;
{
    public AdvancedFilterValidator()
    {
        RuleFor(x =&gt; x.Values).NotEmpty().ForEach(x =&gt; x.MinimumLength(20));
        //RuleForEach(x =&gt; x.Values).MinimumLength(20); (tried both approaches, none of them worked for me)
    }
}

When I try to call my endpoint with invalid paylaod such as

[
  {
     &quot;values&quot;:[&quot;test&quot;]
  }
]

It does not throw Validation exception back at me. Interestingly enough, when I change my controller to accept just a single object like this, the fluent validation suddenly kicks in as expected.

    [HttpPost(&quot;test&quot;)]
    public AdvancedFilter Test(AdvancedFilter filters)
    {
        return filters;
    }

I am using ASP Net Core v 6 with FluentValidation.AspNetCore version "11.3.0" (latest)

Bonus question:
My end goal with this validation is to have ensure that all input values are numbers (even though they are strings, for certain cases I need to make sure they are int). Expanded model would shine more light to it (still simplified)

public class AdvancedFilter
{
    public AdvancedFilterColumn Column { get; set; }
    public List&lt;string&gt; Values { get; set; }
}

public class AdvancedFilterValidator : AbstractValidator&lt;AdvancedFilter&gt;
{
    public AdvancedFilterValidator()
    {
        When(x =&gt; x.Column == AdvancedFilterColumn.Jurisdiction, () =&gt;
        {
            RuleForEach(x =&gt; x.Values).Must(x =&gt; int.TryParse(x, out _));
        });
    }
}

As you can see for specific case, when Column is Jurisdiction I need to make sure that passed in values are all numbers. I believe the validation rule is written correctly, yet I cannot test it (due to abovementioned problem).

Any help in respect to this matter would be highly appreciated.

答案1

得分: 0

Think that you need to build a validator for validating the `AdvancedFilter` collection.

public class AdvancedFilterCollectionValidator : AbstractValidator<IEnumerable<AdvancedFilter>>
{
    public AdvancedFilterCollectionValidator()
    {
        RuleForEach(x => x).SetValidator(new AdvancedFilterValidator());
    }
}

And register the validator service in the ConfigureServices method.

public void ConfigureServices(IServiceCollection services) 
{
    services.AddMvc();

    // Other configurations

    services.AddScoped<IValidator<AdvancedFilter>, AdvancedFilterValidator>();
    services.AddScoped<IValidator<IEnumerable<AdvancedFilter>>, AdvancedFilterCollectionValidator>();
}

Reference: Validation for a for Collection of a type at Root level?


<details>
<summary>英文:</summary>

Think that you need to build a validator for validating the `AdvancedFilter` collection.

```csharp
public class AdvancedFilterCollectionValidator : AbstractValidator&lt;IEnumerable&lt;AdvancedFilter&gt;&gt;
{
    public AdvancedFilterCollectionValidator()
    {
        RuleForEach(x =&gt; x).SetValidator(new AdvancedFilterValidator());
    }
}

And register the validator service in the ConfigureServices method.

public void ConfigureServices(IServiceCollection services) 
{
    services.AddMvc();

    // Other configurations

    services.AddScoped&lt;IValidator&lt;AdvancedFilter&gt;, AdvancedFilterValidator&gt;();
    services.AddScoped&lt;IValidator&lt;IEnumerable&lt;AdvancedFilter&gt;&gt;, AdvancedFilterCollectionValidator&gt;();
}

Reference: Validation for a for Collection of a type at Root level?

huangapple
  • 本文由 发表于 2023年3月31日 02:48:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75891931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定