0

I am writing server code in ASP.NET and using the MVC framework. My client code is javascript.

Whether using JQuery or not to send an AJAX request from browser to server, you can set a timeout, and of course the browser also has a timeout it can enforce seperately. If either of those timeouts are reached, the failure method of the ajax invocation is called and one of the arguments specifies a timeout.

HOWEVER. I have recently discovered, it seems, that the server can timeout an AJAX call, and terminate with a 500 error code, which the client will receive as a 500 error code no different than any unexpected error. However, in this case, the underlying server worker process continues -- it is only the web server itself (IIS in my case) that interrupts and sends a 500 error code without letting the worker know, so that the worker continues on blissfully unaware that there is a problem.

Meanwhile, the client in the error handler for the AJAX call gets a status of 500, which it would naturally interpret as a failure of the worker process, perhaps an unhandled exception and ungraceful termination. As far as I can see, there is no way for the client to KNOW that the problem was a timeout, seperately from an unexpected exception. So the client code might incorrectly assume that the worker process is dead, when in fact it is very much alive.

So.... threefold question:

  1. Is there a way in MVC ASP.NET to control the server timeout settings?
  2. Is there a way for the worker process that the server thinks is taking too long to be informed if the server generates a timeout on its behalf?
  3. Is there a way for the client side AJAX failure callback to know that this particular 500 error is not because the worker had an unexpected error, but because the wrapping server code decided it was taking too long?

w.r.t. #3, I can see that the responseText property of the Ajax response does contain some html that if rendered would tell the user that there was a timeout, but programmatically parsing for that seems really messy and unreliable.

Anyone else run into this?


ADD / EDIT, 4pm PDT on 1/26:

Based on a comment immediately below suggesting that I might find a solution with this article, I implemented the suggested filter. It did not work. I was able to trigger the new filter by explicitly throwing an unhandled timeout exception from the worker process, so my filter as per that other SO article was clearly in play, but it wasn't triggered.

I should add that this application is running as a windows Azure web site. It is my belief from the the circumstantial evidence/data that I have been able to accumulate that IIS on the VM is itself interrupting the request and responding with a 500 error without even telling the underlying worker process or MVC app that it has summarily terminated the request.

So this almost seems like an IT issue of being able to configure IIS on that particular VM for that particular web site.

From my data, it appears that IIS is just canceling the request after 230 seconds.

Community
  • 1
  • 1
Stephan G
  • 3,289
  • 4
  • 30
  • 49
  • How about a custom exception filter and handle `TimeoutException` inside it? May be if its too long running process, I would suggest to use background jobs like hangfire.io or signalR to trigger the client from server about completion – Developer Jan 26 '17 at 16:01
  • What I mean is, have a global filter which would handle TimeoutException and convert the http response status code and message to your desired code md message – Developer Jan 26 '17 at 16:24
  • @Developer - I'm not entirely sure what you mean about this global filter. I believe that that it is IIS that is terminating the request.... if you have more specific instructions or can link me to a place that does I would love to try this. – Stephan G Jan 26 '17 at 17:18
  • I think i got what exactly you need - http://stackoverflow.com/questions/9600530/best-way-of-handling-timeouts-with-asynccontroller – Developer Jan 26 '17 at 17:37
  • Thanks @Developer, but no dice. See the ADD/EDIT to my issue above. Frustrating! – Stephan G Jan 27 '17 at 00:06
  • If the process is taking 230+ seconds to complete, then definitely this is a candidate for background job or async controller – Developer Jan 27 '17 at 02:06

1 Answers1

0

Try this web.config entry:

<system.web>
<httpRuntime executionTimeout="your-timeout-in-seconds">
...
</system.web>
komsky
  • 1,568
  • 15
  • 22
  • Thanks... this looks promising for #1 but will take a while for me to test. Grateful for the fast response. – Stephan G Jan 26 '17 at 16:02
  • But what happens if the process takes even more time than mentioned in the config? – Developer Jan 26 '17 at 16:05
  • @Developer Exactly what you would expect - client get's Internal Server Error. I believe that in the body of http message you have information that this was server timeout, but I'm not sure at the moment. – komsky Jan 26 '17 at 16:07
  • This looked so promising, but sadly from my test, this doesn't do anything. I have tried both setting the number very low and seeing if the AJAX call times out quickly (and there was no change) and setting the number very high and seeing if the AJAX call timed out differently than in previous tests. There was also no change. – Stephan G Jan 26 '17 at 17:16
  • 1
    You didn't mention that IIS is hosted in the Azure cloud. Again, @Developer mentioned correctly that if the process is really over 230 this is bad by design and you should implement this differently. Those limits were placed for a reason, you know? Async two-way communication might be the key. Have you tried SignalR? – komsky Jan 27 '17 at 09:19
  • true, I would suggest something like SignalR and hangfire.io to get this job done – Developer Jan 27 '17 at 09:23
  • Thanks friends. This is part of a larger framework. I'll have to spawn a thread and poll. It is still my strong opinion that Azure should DEFINITELY not respond with a 500 error. Even an Upstream Timeout error would be better. This is just very shoddy error reporting. And although I am not clear on the architecture, Azure should ALSO do everything it can to ensure that an exception is thrown in the worker process itself, so it doesn't keep on merrily executing after a timeout has been thrown on its behalf. – Stephan G Jan 30 '17 at 15:06