Skip to content

[Breaking change]: Updated empty body detection in MVC Model Binding #484

Open
@brunolins16

Description

@brunolins16

Description

The mechanism to detect an empty request body during the MVC Model Binding now uses the IHttpRequestBodyDetectionFeature.CanHaveBody, that is currently implemented by the following behavior:

  • true when:

    • It's an HTTP/1.x request with a non-zero Content-Length or a Transfer-Encoding: chunked header.
    • It's an HTTP/2 request that did not set the END_STREAM flag on the initial headers frame.
  • false when:

    • It's an HTTP/1.x request with no Content-Length or Transfer-Encoding: chunked header, or the Content-Length is 0.
    • It's an HTTP/1.x request with Connection: Upgrade (e.g. WebSockets). There is no HTTP request body for these requests and no data should be received until after the upgrade.
    • It's an HTTP/2 request that set END_STREAM on the initial headers frame.

Since the previous behavior was a simple validation of the Content-Length == 0, in some scenarios when requests are not sending all needed HTTP information, could now be detected as empty request and report a failure to the client.

Version

7.0.0-preview3

Previous behavior

Before if you have a Controller's action that bind a parameter from body:

 [HttpPost()]
        public IActionResult Required([FromBody] TestClass value) => Ok(value);

And the client request does not include a Content-Length header, eg.:

curl --request POST -k -i "[action]" -H "Content-Type: application/json"

This request will cause an internal exception during the body deserialization:

Eg.: When using the System.Text.Json input formatter

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.'

Also, a response payload similar to this will be receive by the client:

{
  "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

With the updated detection mechanism, the deserialization will not be trigger since an empty request body will be detected and only a validation message will be reported back to the client. Eg.:

{
  "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

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
  • Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.

Reason for change

This change is an alignment with other parts of the framework that were already using the IHttpRequestBodyDetectionFeature.CanHaveBody and also a fix to a reported issue dotnet/aspnetcore/issues/29570

Recommended action

No change is required, however, if you getting an unexpected behavior is recommended to review if your client's requests are sending the appropriated headers/information.

Affected APIs

MVC Action Controllers

Metadata

Metadata

Assignees

No one assigned

    Labels

    7.0.0Breaking changeDocumentedThe breaking change has been published to the .NET Core docs

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions