asp.net-mvcazuretimeoutazure-web-app-serviceapplicationhost

Azure App Service Set Custom ConnectionTimeout in ApplicationHost.config


On our ASP.NET MVC website hosted on Azure App Service we'd like to force a timeout for requests that take longer than 15 seconds. Here's a simple action that always takes longer than 15 seconds (i.e. infinite loop) that we've been testing with...

    public ActionResult TimeoutTest()
    {
        var i = 1;
        while (true)
        {
            i++;
        }
        return new HttpStatusCodeResult(200);
    }

By default, if I do a GET on that action in a browser, I'll get a "500 - The request timed out" error after two minutes, which agrees with the "connectionTimeout" default setting in the webLimits section of ApplicationHost.config.

So...unless I'm mistaken, it should be enough to change this connectionTimeout value to 15 seconds. To do this, I understand one needs to use a transform-based approach for the ApplicationHost.config file (XDT), as explained here.

I did this with the following applicationHost.xdt file...

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
      <webLimits xdt:Transform="SetAttributes(connectionTimeout)" connectionTimeout="00:00:15"/>
</system.applicationHost>
</configuration>

...after which I added the file in the right place (d:/home/site/applicationHost.xdt). I restarted my site and saw in the logs that the transform was successfully applied:

2016-04-20T08:40:44 Start 'site' site extension transform
2016-04-20T08:40:44 StartSection Executing SetAttributes (transform line 4, 18)
2016-04-20T08:40:44 on /configuration/system.applicationHost/webLimits
2016-04-20T08:40:44 Applying to 'webLimits' element (no source line info)
2016-04-20T08:40:44 Set 'connectionTimeout' attribute
2016-04-20T08:40:44 Set 1 attributes
2016-04-20T08:40:44 EndSection Done executing SetAttributes
2016-04-20T08:40:44 Successful 'D:\home\site\applicationHost.xdt' site extension transform
2016-04-20T08:40:44 sandboxproc.exe complete successfully. Ellapsed = 316.00 ms

[Edit]: I have also checked the applicationhost.config directly after the transform, and the new value is there:

    ...
    </sites>
    <webLimits connectionTimeout="00:00:15" />
  </system.applicationHost>
  <system.webServer>
    <asp>
    ...

Despite all this, if I hit my action method above again, it still times out after two minutes instead of 15 seconds.

My question: Does anybody know why this timeout setting isn't being respected?

I'm aware of this post, which looks like it took exactly the same approach (and seemed to work?).


Solution

  • What about using executionTimeout instead, through the Web.Config?

    <system.web>
        <httpRuntime executionTimeout="30" />
        <compilation debug="false" />
    </system.web>
    

    For a MVC project, you should add the following code to force the value to be applied to the request:

    System.Web.HttpContext.Current.GetType().GetField("_timeoutState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(System.Web.HttpContext.Current, 1);
    

    If you want every request to respect this setting, you can create an action filter:

    public class Timeoutter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            System.Web.HttpContext.Current.GetType().GetField("_timeoutState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(System.Web.HttpContext.Current, 1);
            base.OnActionExecuting(filterContext);
        }
    }
    

    Add register it in the RegisterGlobalFilters method called in the Global.asax:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new Timeoutter());
        filters.Add(new HandleErrorAttribute());
    }
    

    Please see: