How to set different Timeouts for different URLs in ASP.NET

Gareth Farrington picture Gareth Farrington · Jun 17, 2011 · Viewed 33.4k times · Source

I want different connection limits for some URLs in my application. Some URLs accept file uploads and need to have a large Connection Timeout. All other URLs need a much smaller timeout to prevent denial of service and not waste resources.

Currently I have the Connection Timeout property in IIS set for the entire site to 60 minutes. Then I did this in the web.config:

<system.web>
    <httpRuntime executionTimeout="480" maxRequestLength="1024" />
</system.web>

<location path="FileUpload/WriteFile.rails">
    <system.web>
        <httpRuntime executionTimeout="3600" maxRequestLength="512000" />
    </system.web>
</location>

So i was hoping this would set all URLs to an 8 minute timeout and allow the WriteFile.rails URL to run for 60 minutes. Instead ALL URLs are allowed to run for 60 minutes. How do I get IIS to do what I want?

Answer

Gareth Farrington picture Gareth Farrington · Jul 5, 2011

The question asked specifically about timeouts but also implied setting maxRequestLength as well. I'm going to try and give a really comprehensive answer to both issues (now that I have spent most of a day working it out).

Lets say we have a single URL on our website that we want to process file uploads. We want to take in up to a Gigabyte of data on that URL and we will allow clients to be connected for, at most, 1 hour. All other URLs we want to only allow 90 seconds of connection time and a maximum of 4MB in the POST body.

Global Settings

First you have to globally raise the limits on time and size for the entire site. First you want to set the "Connection Timeout" for the entire site. This acts as an absolute upper bound and it cannot be set from within the web.config. The IIS7 website has good instructions here. You can also do it programatically with the Microsoft.Web.Administration library that shipped with IIS7/7.5:

var serverManager = ServerManager.OpenRemote("\\web-server-name");
var site = serverManager.Sites["Your-Site-Name"];
site.Limits.ConnectionTimeout = new TimeSpan(1, 0, 0);

Next you need to set the max size request that the site will allow. This is in a totally different place, in the Request Fitlering module. This module may not be installed by default on IIS7. Again Microsoft has good instructions for how to set the maxAllowedContentLength through the GUI. This is something you can set from within the Web.config:

<system.webServer>
    <security>
        <requestFiltering>
            <!-- Allow 1GB uploads -->
            <requestLimits maxAllowedContentLength="1073741824"></requestLimits>
        </requestFiltering>
    </security>
</system.webServer>

This setting is evaluated against the Content-Length header and requests larger than this will immediately result in a 404.13. The setting is in bytes and what comes next is in Kilobytes, very consistent this IIS7.

ASP.NET Settings

Next we want to cap all of the ASP.NET requests at 90 seconds/4MB. This can be done in the web.config:

<location>
    <system.web>
        <httpRuntime executionTimeout="90" maxRequestLength="4096" />
    </system.web>
</location>

To make the settings global the system.web tag is wrapped in a location tag that has no path attribute. (In the original question I did not wrap the system.web tag in the location tag which was probably the source of my problem.) maxRequestLength is in kilobytes this time.

Finally we want to allow our special upload URL to accept huge uploads. Setting these values higher than the ones you set globally wont work. The global values override these settings.

<location path="Uploads/PostFile.rails">
    <system.web>
        <httpRuntime executionTimeout="3600" maxRequestLength="1048576" />
    </system.web>
</location>

If everything else is set up right, that should do it. As Peter Bromberg suggested, you can add as many of these blocks as needed to raise the limits for specific URLs.

One last note: in debug mode IIS does not enforce the Connection Timeout or executionTimeout settings, to allow you more time for debugging. So to test your setting on a developer machine you should do a release build and you should set the 'Enable Server-Side Debugging' setting to false.