Summary
#3372 (fixed in 6.17.1 / 6.17.2) made an unparseable scalar query string value return 400 Bad Request instead of silently binding the property's default. The same failure mode is still present for collection / array query string parameters bound through [AsParameters].
When one member of a multi-value query parameter cannot be parsed, the whole collection binds to null and the request succeeds with 200 OK. The endpoint cannot distinguish that from "the caller did not send the parameter at all".
Version
WolverineFx / WolverineFx.Http 6.17.2, .NET 10.
Repro
public enum Colour { Red, Green, Blue }
public record SearchRequest
{
public Colour[]? Colours { get; set; }
public Colour? Colour { get; set; }
}
public static class SearchEndpoint
{
[WolverineGet("/widgets")]
public static IResult Get([AsParameters] SearchRequest request)
=> Results.Ok(new { colours = request.Colours, colour = request.Colour });
}
| Request |
Actual (6.17.2) |
Expected |
GET /widgets?colour=Purple |
400 Bad Request ✅ (fixed by #3372) |
400 |
GET /widgets?colours=Purple |
200 OK, Colours == null ❌ |
400 |
GET /widgets?colours=Red&colours=Purple |
200 OK, Colours == null ❌ |
400 |
The same holds for int[] / Guid[] / long[] collections, not just enums — any element whose TryParse fails takes the entire collection to null.
Why this is worse than a plain 400
On a filtering/search endpoint, the bound collection is typically used as an optional predicate:
if (request.Colours is { Length: > 0 })
{
query = query.Where(x => request.Colours.Contains(x.Colour));
}
A typo in one value therefore does not fail the request — it silently removes the filter and returns an unfiltered result set with a 200, while the caller believes the results are filtered. That is a silent-wrong-answer failure mode rather than a loud one.
Validation cannot compensate
FluentValidation (via WolverineFx.Http.FluentValidation) sees null, not an out-of-range value, so neither of these fires:
RuleForEach(x => x.Colours).IsInEnum(); // no elements to iterate
RuleFor(x => x.Colours).NotEmpty().When(x => x.Colours is not null); // it *is* null
There is no way, from inside the handler or a validator, to tell "unparseable value supplied" apart from "parameter omitted". The information is lost in the binder.
Expected behaviour
A collection query string parameter whose element fails to parse should fail the request with 400 Bad Request, consistent with the scalar behaviour introduced by the fix for #3372.
Summary
#3372 (fixed in 6.17.1 / 6.17.2) made an unparseable scalar query string value return
400 Bad Requestinstead of silently binding the property's default. The same failure mode is still present for collection / array query string parameters bound through[AsParameters].When one member of a multi-value query parameter cannot be parsed, the whole collection binds to
nulland the request succeeds with200 OK. The endpoint cannot distinguish that from "the caller did not send the parameter at all".Version
WolverineFx / WolverineFx.Http 6.17.2, .NET 10.
Repro
GET /widgets?colour=Purple400 Bad Request✅ (fixed by #3372)400GET /widgets?colours=Purple200 OK,Colours == null❌400GET /widgets?colours=Red&colours=Purple200 OK,Colours == null❌400The same holds for
int[]/Guid[]/long[]collections, not just enums — any element whoseTryParsefails takes the entire collection tonull.Why this is worse than a plain 400
On a filtering/search endpoint, the bound collection is typically used as an optional predicate:
A typo in one value therefore does not fail the request — it silently removes the filter and returns an unfiltered result set with a
200, while the caller believes the results are filtered. That is a silent-wrong-answer failure mode rather than a loud one.Validation cannot compensate
FluentValidation (via
WolverineFx.Http.FluentValidation) seesnull, not an out-of-range value, so neither of these fires:There is no way, from inside the handler or a validator, to tell "unparseable value supplied" apart from "parameter omitted". The information is lost in the binder.
Expected behaviour
A collection query string parameter whose element fails to parse should fail the request with
400 Bad Request, consistent with the scalar behaviour introduced by the fix for #3372.