Today I learned the hard way that since ASP.NET Core 2.0, the request body has acquired a default size limit at 30MB (~28.6 MiB).

If the request body size exceeds the configured max request body size limit, the call to Request.Body.ReadAsync will throw an IOException. If this exception is uncaught, Kestrel will respond with a 413 Payload Too Large response and HttpSys will respond with a generic 500 Internal Server Error response (source).

This will be a breaking change if your endpoint is expected to handle large uploads. The solution is simple, just decorate your MVC action or controller with the RequestSizeLimit attribute, like so:

    [HttpPost]
    [RequestSizeLimit(100_000_000)]
    public IActionResult MyAction([FromBody] MyViewModel data)
    {

DisableRequestSizeLimit can be used to make request size unlimited. This effectively restores pre-2.0.0 behavior for just the attributed action or controller. You can also change or disable the limit programmatically, either on a per-request basis or globally (see the instructions at this link.)

In my case, however, disabling the request limit was not enough. Because my endpoint is expecting an IFormFile argument, I also had to set the RequestFormLimits attribute:

    [HttpPost]
    [DisableRequestSizeLimit,
    RequestFormLimits(MultipartBodyLengthLimit = int.MaxValue, 
        ValueLengthLimit = int.MaxValue)]
    public async Task<ActionResult> BulkAdd(string schema, IFormFile file)
    {

Please note that all of this happened on a .NET 5 Linux application with Kestrel running behind nginx. As pointed out at the link above, if you’re running behind IIS, then the limit is disabled, and the usual web.config limit applies.

For future reference, here are the current Kestrel limits.