Reputation: 2468
I have example mode class:
public class Data
{
[Required]
[MinLength(1)]
public List<Foo> Foos{ get; set; }
}
which is passed to controller:
[ApiController]
public class FooController : ControllerBase
{
public async Task<IActionResult> Post([FromBody] Data data)
{
// Do stuff
}
}
I have nullable annotations enabled in my project configuration.
How can I force model validator to reject request with null foos array? For example following request is accepted by controller:
{
foos: [null]
}
I would like such request to return bad request status code.
Upvotes: 2
Views: 1754
Reputation: 36595
You could custom ValidationAttribute to custom the rule:
Custom ValidationAttribute:
public class ValidArray : ValidationAttribute
{
protected override ValidationResult
IsValid(object value, ValidationContext validationContext)
{
var model = (Data)validationContext.ObjectInstance;
if(Extension.IsNullOrEmpty<Foo>(model.Foos))
{
return new ValidationResult
("Array cannot be null");
}
else
{
return ValidationResult.Success;
}
}
}
Custom IsNullOrEmpty
:
public static class Extension
{
public static bool IsNullOrEmpty<T>(List<T> array) where T : class
{
if (array == null || array.Count == 0)
return true;
else
return array.All(item => item == null);
}
}
Model:
public class Data
{
//[Required]
[MinLength(1)]
[ValidArray]
public List<Foo> Foos { get; set; }
}
public class Foo
{
public int Id { get; set; }
public int Count { get; set; }
}
Result:
Upvotes: 1
Reputation: 2071
When using Data Annotations the child classes are not validated. I recommend Fluent Validation for the use case presented.
The use is simple, just define a rule
public class DataValidator : AbstractValidator<Data>
{
public DataValidator()
{
// RuleFor(r => r.Foos).NotEmpty(); // <-- not needed as Nullable Annotations are enabled
RuleForEach(r => r.Foos).NotNull();
}
}
And register FluentValidation
in configure services method
services.AddControllers()
.AddFluentValidation(configuration => configuration.RegisterValidatorsFromAssemblyContaining<Startup>());
Upvotes: 2