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.