dotnet / dotnet/aspnetcore

Modelbinding/AntiForgery validation suppresses IOException/BadHttpRequestException

Open
#40,810 9 comments 1 reaction 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

Upgrading from 3.1 to 6.0, and a multipart body exceeding the configured MaxHttpRequestBodySize no longer produces an error response (or a response at all).

Under 3.1 attempting this would produce the trace:

```
at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.OnReadStarting()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.TryStart()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.BufferedReadStream.EnsureBufferedAsync(Int32 minCount, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool`1 bytePool, Nullable`1 limit, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.ReadNextSectionAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.TryCreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
```

Interestingly the log reports:

```
[2022-03-21 17:26:39.0396][INFO][Microsoft.AspNetCore.Hosting.Diagnostics] Request finished HTTP/1.1 POST http://localhost:57513/api/modules/irams/attachments multipart/form-data;+boundary=---------------------------344584781640975190543136916438 34166185 - 500 - text/plain;+charset=utf-8 90.6786ms
[2022-03-21 17:26:39.0396][DEBUG][Microsoft.AspNetCore.Server.Kestrel.BadRequests] Connection id "0HMGBG5LMMVRR" bad request data: "Request body too large. The max request body size is 33554432 bytes."Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large. The max request body size is 33554432 bytes.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.OnReadStarting()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.TryStartAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.ConsumeAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
[2022-03-21 17:26:39.0396][DEBUG][Microsoft.AspNetCore.Server.Kestrel.Connections] Connection id "0HMGBG5LMMVRR" disconnecting.
[2022-03-21 17:26:39.0396][DEBUG][Microsoft.AspNetCore.Server.Kestrel.Connections] Connection id "0HMGBG5LMMVRR" stopped.
[2022-03-21 17:26:39.0396][DEBUG][Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets] Connection id "0HMGBG5LMMVRR" resumed.
[2022-03-21 17:26:39.0396][DEBUG][Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets] Connection id "0HMGBG5LMMVRR" sending FIN because: "The Socket transport's send loop completed gracefully."
```

But what I actually get is a closed connection (no response), and a ModelBinding error with a null IFormFile on the server.

This appears to be caught by FormValueProviderFactory per 78a587b02ebce99493a8e9b8c417ecbbbee457ce:

https://github.com/dotnet/aspnetcore/blob/57c3104f0d19bb9e25b8ba75b422e2d6072e1dd5/src/Mvc/Mvc.Core/src/ModelBinding/FormValueProviderFactory.cs#L50-L55

### Expected Behavior

Any request exceeding MaxRequestBodySize should produce an HTTP 413: Payload too large.

### Steps To Reproduce

_No response_

### Exceptions (if any)

_No response_

### .NET Version

6.0.102

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.