By default, ASP.NET and IIS protect us from large requests by putting hard limits on the transmitted size. IIS buffers files in our server’s memory before passing the byte array to ASP.NET. IIS’ default limit is 4MB and ASP.NET Core has a default of 30MB. To put that in perspective, one 12 megapixels digital picture can average 3.6 megabytes.

Imagine a 4-gigabyte file being uploaded from multiple sources to our server at the same time. The thought is wince-inducing because most servers would be freaking out at this point. So how do we increase the request size limit? Here are a few steps we will need to follow.

ASP.NET Core

The ASP.NET Core section was adapted from a GitHub issue response.

Starting in ASP.NET Core 2.0.0, both Kestrel and HttpSys began enforcing a 30MB (~28.6 MiB) max request body size limit.

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.

This limit can be changed either globally or on a per-request basis and is disabled for Kestrel running behind IIS, where the standard web.config limit still applies.

If we are hosting in IIS, we can skip to the IIS Configuration section.

MVC Instructions

If we want to change the max request body size limit for a specific MVC action or controller, we can use the RequestSizeLimit attribute. The following will allow MyAction to accept request bodies up to 100,000,000 bytes.

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

We can also use the DisableRequestSizeLimit attribute to allow our controller actions to accept unlimited sized requests.

Generic Middleware Instructions

If an MVC action is not handling the request, the limit can still be modified on a per request basis using the IHttpMaxRequestBodySizeFeature. For example:

app.Run(async context =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = 100_000_000;

MaxRequestBodySize is a nullable long. Setting it to null disables the limit like MVC’s DisableRequestSizeLimit attribute.

We can only configure the limit on a request if the application hasn’t started reading yet; otherwise, our app will throw an exception.

There’s an IsReadOnly property that tells us if the MaxRequestBodySize property is in read-only state. If the property’s value is true, that means it’s too late to configure the limit.

Global Config Instructions

If we want to modify the max request body size globally, we can modify a MaxRequestBodySize property in the callback of either UseKestrel or UseHttpSys. MaxRequestBodySize is a nullable long in both cases.

.UseKestrel(options =>
{
    options.Limits.MaxRequestBodySize = null;
.UseHttpSys(options =>
{
    options.MaxRequestBodySize = 100_000_000;

ASP.NET 3+

These changes should occur in our applications web.config files, as they will be read and processed by the instance of IIS hosting our application. The configuration applies to old .NET Framework applications as well as .NET Core applications.

<configuration>
  <system.web>
      <!-- This will handle requests up to 50MB (in kilobytes) -->
      <httpRuntime targetFramework="4.5" maxRequestLength="51200" />
  </system.web>
</configuration>

We need to add a maxRequestLength attribute to our httpRuntime element in our web.config. Note the configuration value is in kilobytes. The default is 4096 KB. If the threshold is exceeded, a ConfigurationErrorsException exception is thrown.

[maxRequestLength] Specifies the limit for the input stream buffering threshold, in KB. This limit can be used to prevent denial of service attacks…Microsoft

We should also increase the executionTimeout value if the transmitted file sizes are going to be “large”. We should experiment with the number of seconds, but by default, the execution timeout is around 110 seconds.

[executionTimeout] specifies the maximum number of seconds that a request is allowed to execute before being automatically shut down by ASP.NET. Microsoft

This execution time-out applies only if the debug attribute in the compilation element is set to False with a default is 110 seconds.

This is important and worth repeating. The execution timeout does not apply while in debug mode. We might notice uploads work locally in development, but not in production. We need to make sure to test it in our development environment in a release configuration.

IIS Configuration

We will need to configure IIS to let large requests through to our apps. We need to set the requestLimits value in a web.config at the root of our apps hosting directory.

<system.webServer>
   <security>
      <requestFiltering>
         <!-- This will handle requests up to 50MB (in bytes) -->
         <requestLimits maxAllowedContentLength="52428800" />
      </requestFiltering>
   </security>
</system.webServer>

By default, IIS will throw a 404 exception if the file is larger than the limit. Note, the maxAllowedContentLength setting is in bytes not kilobytes, unlike the other settings found in this post.

Conclusion

There we have it, we have just increased the request limit in our ASP.NET application. We must think about these settings and choose values diligently. Uploading large files in parallel to a single server can paralyze it. We need to be sure to pick our size accordingly and don’t just set it to the max of 4 gigabytes. I hope you found this post helpful.