I have trouble finding a way to validate items in a sequence for .NET Core configuration (tried with .NET 5 and 3.1).
Say that my settings are like so:
{
"MyOpt": {
"IntOpt": 5,
"StrOpt": "...",
"Inner": {
"InnerStr": "...",
"InnerInt": 7
},
"Inners": [
{
"InnerStr": "...",
"InnerInt": 1
},
{
"InnerStr": "...",
"InnerInt": 2
}
]
}
}
public class Inner
{
public string InnerStr { get; set; }
[Range(0, 1000, ErrorMessage = "Value {0} must be between {1} and {2}")]
public int InnerInt { get; set; }
}
public class MyOpt
{
[Range(0, 1000, ErrorMessage = "Value {0} must be between {1} and {2}")]
public int IntOpt { get; set; }
public string StrOpt { get; set; }
public IEnumerable<Inner> Inners { get; set; }
}
And that I configure this in my Startup.cs like so:
services
.AddOptions<MyOpt>()
.Bind(Configuration.GetSection("MyOpt"))
.ValidateDataAnnotations();
When I try to access this from, say in a controller in a WebAPI:
public HomeController(ILogger<HomeController> logger, IOptions<OptOpt> options)
{
var whatever = options.Value.IntOpt;
_logger = logger;
}
Validations kick in correctly for MyOpt.IntOpt or MyOpt.Inner.InnerInt (both data annotations and conversion errors cause an exception to be thrown, e.g. for
{
"MyOpt": {
"IntOpt": "abc",
...
}
I get a nice
ArgumentException: abc is not a valid value for Int32. (Parameter 'value').
However, if one of MyOpt.Inners items is misconfigured, it is silently dropped, e.g. for
{
"MyOpt": {
// ...
"Inners": [
{
"InnerStr": "...",
"InnerInt": 1
},
{
"InnerStr": "...",
"InnerInt": "abc"
}
]
}
}
I only get one item in MyOpt.Inners (the first one) and I can't seem to find a way for this to somehow "participate" in the validation - or that the binding failure of "abc" is reported through an exception.
Any idea?