The default binding model
For attributed controller methods, the router infers where values come from:- For
POST,PUT, andPATCH, one class-type parameter is treated as the request body - Parameters whose names match route placeholders are read from the route
- Remaining scalar parameters are read from the query string
Implicit binding example
Body— from the JSON bodyOrderId— from/orders/[orderId]Sort— from?sort=...
Explicit binding example
[FromBody][FromRoute][FromQuery]
Important binding rules
- Only one body parameter is allowed
[FromBody]is only valid onPOST,PUT, andPATCH[FromBody]must target a class-type parameter- Missing required route or query values return
400 Bad Request - Nullable query parameters can be omitted and bind as
null
IParameterNameCodec, so the JSON payload must follow the router’s configured naming convention.
Built-in conversions beyond strings
The current binder supports more than just basic strings and body objects.- Enums can bind from route values, query values, and body fields
DateTimeOffset,DateOnly,TimeOnly, andTimeSpancan bind from route, query, and body data when the incoming value is convertible
Transport validation attributes
The current binding pipeline also validates parameters and bound body models before the controller action runs.NonEmptyNonDefaultStringLength(min, max)Range(min, max)EmailFormatUrlFormat
ValidateElements = true on collection validators when each element should be checked individually.
When validation fails, the router returns 400 Bad Request before the controller action runs.
Returning JSON
Non-raw controller methods should returnTask<T>. The returned object is serialized to JSON automatically.
Returning errors
For attributed methods, throw an HTTP exception:RestApiErrorResponse— simple{ message, error_code }payloadClientError— carries status code, message, localization key, and error codeExpected<T, E>— models success and failure explicitly before converting to HTTP
internal_server_exception.
Validation field paths use the active parameter-name codec for body properties. If you switch to snake case, validation messages follow that same JSON-facing naming.