You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When an [AsParameters] query model has a non-nullable enum (or any value-typed) property with a default initializer, Wolverine's generated query-string binder silently ignores an unparseable value and leaves the property at its initializer. The request then succeeds with the default semantics instead of being rejected.
ASP.NET Core's own minimal-API [AsParameters] binder returns 400 Bad Request for the same input, so the behaviour differs from the framework the attribute is borrowed from.
The practical consequence is that a typo'd query value is indistinguishable from an absent one, so there is no way to reject it — not even downstream. A FluentValidation IsInEnum() rule can't catch it either: the binder never writes an out-of-range value (such as 0) that the validator could see, it just doesn't assign at all.
The same holds for int / long / Guid properties: ?page-size=abc binds to the initializer rather than failing.
Expected
An unparseable value for a bound query parameter should be reportable. Any of these would resolve it:
return 400 on a failed parse, matching ASP.NET Core's [AsParameters] binder;
make it opt-in (e.g. a WolverineHttpOptions flag) so existing lenient behaviour is preserved by default;
at minimum, record the failure somewhere an endpoint or middleware can observe (e.g. as a binding-problem collection on the HttpContext), so a policy can turn it into a 400.
Agreed this is wrong as it stands — silently keeping the initializer value on an unparseable enum/int/Guid is worse than either strictness or leniency, because not even FluentValidation can see it downstream: by the time validation runs, the value looks legitimate.
Behavior decision, since matching ASP.NET minimal APIs outright (400 on parse failure) would be a breaking behavior change for existing lenient apps:
Now (6.x): an opt-in flag on WolverineHttpOptions (working name RejectUnparseableQueryValues). With it on, a TryParse failure in the generated query binder short-circuits to a 400 with ProblemDetails naming the offending parameter — same contract as minimal APIs.
7.0: the flag's default flips, making strict binding the standard behavior and leniency the opt-out.
The missing-vs-malformed distinction stays: an absent query value keeps the parameter's initializer in both modes; only a present but unparseable value triggers the 400.
Implementation is small and scheduled in the current community-issue sweep, along with a "strict binding" section in the [AsParameters] docs.
Activity
jeremydmiller commentedon Jul 12, 2026
Agreed this is wrong as it stands — silently keeping the initializer value on an unparseable enum/int/Guid is worse than either strictness or leniency, because not even FluentValidation can see it downstream: by the time validation runs, the value looks legitimate.
Behavior decision, since matching ASP.NET minimal APIs outright (400 on parse failure) would be a breaking behavior change for existing lenient apps:
WolverineHttpOptions(working nameRejectUnparseableQueryValues). With it on, aTryParsefailure in the generated query binder short-circuits to a 400 with ProblemDetails naming the offending parameter — same contract as minimal APIs.The missing-vs-malformed distinction stays: an absent query value keeps the parameter's initializer in both modes; only a present but unparseable value triggers the 400.
Implementation is small and scheduled in the current community-issue sweep, along with a "strict binding" section in the
[AsParameters]docs.Opt-in strict query string binding: 400 + ProblemDetails for unparsea…
jeremydmiller commentedon Jul 12, 2026
Shipped in Wolverine 6.17.2, now on nuget.org.
[AsParameters]: reject unparseable values in collection query paramet…