I have come across this thread already, but I might need something else for my situation.
I have an action that returns a ViewResult
, which is called by the client's $.post()
JavaScript:
var link = 'GetFoo?fooBar=' + fooBar;
var jqxhr = $.post(link, function (response) {
$('#myDiv').replaceWith(response);
});
Controller:
public ViewResult GetFoo(String fooBar)
{
if (Request.IsAjaxRequest())
{
// perform a ridiculously long task (~12 minutes)
// algorithm: 1) download files from the Azure blob storage
// 2) update each file
// 3) reupload to blob storage
// 4) return a list of URIs to be displayed to the UI
return View("MyFooView", data);
}
throw new InvalidOperationException();
}
As the comment implies, there is long task running inside the Controller. (This is a document generation module that uploads PDFs to the Azure blob storage and returns a link to it to the View.)
This is working fine in my dev machine but when it goes live in a (secure) Azure production environment, it times out. I have put in lots of logging entries everywhere and as it turns out, it is able to upload the documents and return to the controller (i.e. it reaches the controller return statement above). However, when it is time to return the model data to the View, the client script doesn't called back (i.e. the div
content doesn't get replaced with the results).
Is there a way to somehow prolong the timeout of the call? It is difficult to reproduce in my (unsecure) local environment so a definitive fix will help.
If I use the attribute [AsyncTimeout(3600)]
on my GetFoo()
method, then this action never gets called from the UI.
Any suggestions will be appreciated.
To use Async controllers your controller has to inherit from AsyncController:
And then any Action using Asynchronous methods has to use the format of
Where ActionName is the name of your action, and instead of the Async function use
each time you start a new aysnchronous method and
when the method finishes, after all outstanding operations have completed it'll move along to the Completed function (make sure to specify the parameters you need for the completed function in the async function so it knows what to pass along)
Then using the AsyncTimeout attribute would actually affect the function. I'm not sure what happens if you try to apply that attribute to a action that isn't in an async controller.
These changes wouldn't require changing any of the references to the action in the javascript and what not as you'd still just request 'ActionName' and it would look to see if there was the Async/Completed setup version and if not it'd look for just that normal action and use whichever it finds.
The problem is that the Azure load balancer has it's own timeout which is set to one minute. Any request that takes longer than a minute gets terminated. There is no way to change this.
The way around this in the Azure environment is to have one ajax call start the process and return some sort of process ID then have the client poll another ajax call to passing in this process ID to see if it's complete. It might looks something like this uncompiled and untested code. In javascript:
And in your controller:
Hopefully that will give you a starting point.
you want to look at this
answer to your question is: [AsyncTimeout(3600000)]
see more here Controller Timeout MVC 3.0