MVC's detection of an empty body in model binding changed
The mechanism to detect an empty request body during MVC model binding now uses IHttpRequestBodyDetectionFeature.CanHaveBody. This property is set to:
true
:- For
HTTP/1.x
requests with a non-zeroContent-Length
request header or aTransfer-Encoding: chunked
request header. - For
HTTP/2
requests that don't set theEND_STREAM
flag on the initial header's frame.
- For
false
:- For
HTTP/1.x
requests with noContent-Length
orTransfer-Encoding: chunked
request headers, or if theContent-Length
request header is0
. - For
HTTP/1.x
requests with aConnection: Upgrade
request header, such as for WebSockets requests. There's no HTTP request body for such requests, so no data should be received until after the upgrade. - For
HTTP/2
requests that set theEND_STREAM
flag on the initial header's frame.
- For
The previous behavior performed a minimal validation of Content-Length = 0
. In some scenarios, when requests don't include all required HTTP headers and flags, request bodies can now be detected as having an empty body and report a failure to the client.
Version introduced
ASP.NET Core 7.0
Previous behavior
If a controller action binds a parameter from the request body and the client request doesn't include a Content-Length
request header, the framework throws an internal exception during deserialization of the request body. For example, the System.Text.Json
-based input formatter throws an exception similar to the following:
System.Text.Json.JsonException: 'The input does not contain any JSON tokens.
Expected the input to start with a valid JSON token, when isFinalBlock is true.
Path: $ | LineNumber: 0 | BytePositionInLine: 0.'
The following example JSON shows the previous exception formatted as a ProblemDetails response:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-34e98b5841b88bfb5476965efd9d9c8c-5bb16bc50dfbabb7-00",
"errors": {
"$": [
"The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."
],
"value": [
"The value field is required."
]
}
}
New behavior
Deserialization is no longer attempted if IHttpRequestBodyDetectionFeature.CanHaveBody is false
. The following example ProblemDetails response shows how the error message returned to clients indicates that the request body is empty:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-0f87920dc675fdfdf8d7638d3be66577-bd6bdbf32d21b714-00",
"errors": {
"": [
"A non-empty request body is required."
],
"value": [
"The value field is required."
]
}
}
Type of breaking change
This change affects binary compatibility.
Reason for change
To align with other parts of the framework that use IHttpRequestBodyDetectionFeature.CanHaveBody and to fix Optional [FromBody]
Model Binding is not working (dotnet/aspnetcore #29570).
Recommended action
No changes are required. However, if you're seeing unexpected behavior, ensure that client requests send the appropriate HTTP headers.
Affected APIs
MVC controller actions