これが私の問題を解決した方法です。このソリューションは、不当なタイムアウトのあるロードバランサーを使用するすべての.netホスティングに適用できるはずです。Rackspace Cloud Sitesでは、ロードバランサーで30秒のタイムアウトが発生します。AmazonとAzureのタイムアウトは長くなりますが、長時間実行する操作がある場合は、これが有用なソリューションになる可能性があります。
asp.net mvc 4では、AsyncControllerから継承するようにコントローラーを変更できます。これにより、非同期タスクをスピンオフして、それらの完了を待つことができます。このソリューションは、ロードバランサーがアクティビティを検出してタイムアウトしないように、10秒ごとにasp.net応答を介してデータを送り返す「キープアライブ」タスクを作成します。このタスクは、uploadFinished変数がtrueに設定されていることを確認するまで実行されます。
もう1つのタスクは、長時間実行されるアップロード、またはasp.netmvcコントローラーが処理しているWeb要求を終了する前に完了する必要のあるタスクを実行します。長時間実行操作が完了すると、uploadFinished変数がtrueに設定されます。
最後に、実際のjson応答の周りにコンテナーjsonオブジェクトを手動で構築しているので、「キープアライブ」データをブラウザーに返送される有効なjsonの一部にすることができます。少し醜いハックですが、うまくいきます!
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace MvcApplication4.Controllers
{
public class ExampleController : AsyncController
{
[HttpPost]
public string Upload(UploadModel model, HttpPostedFileBase videoFile)
{
// when using jquery ajax form for upload
// IE requires text/plain content type
// otherwise it will try to open the response as a file
// instead of pass the response back to your javascript
if (Request.AcceptTypes.Contains("application/json"))
{
Response.ContentType = "application/json";
}
else
{
Response.ContentType = "text/plain";
}
// start json object
Response.Write("{\"keepalive\":\"");
Response.Flush();
Task[] tasks = new Task[2];
tasks[0] = Task.Factory.StartNew(() => DoKeepAlive());
tasks[1] = Task.Factory.StartNew(() => DoUpload(model, videoFile));
Task.WaitAll(tasks);
// end keepalive json property
Response.Write("\",\"data\":");
// insert actual response data
JavaScriptSerializer json = new JavaScriptSerializer();
Response.Write(json.Serialize(uploadResponse));
// end json object
Response.Write("}");
return "";
}
public bool uploadFinished = false;
public UploadResponseModel uploadResponse = null;
public void DoUpload(UploadModel model, HttpPostedFileBase videoFile)
{
// do upload to 3rd party
MyServiceClient c = new MyServiceClient();
uploadResponse = c.UploadVideo(model, videoFile);
uploadFinished = true;
}
public void DoKeepAlive()
{
// send . every 10 seconds
while (!uploadFinished)
{
Response.Write(".");
Response.Flush();
Thread.Sleep(10000);
}
}
}
}
このソリューションは、非同期処理を行うために.Net4に依存しています。.Net 4.5を使用している場合、AsyncControllerクラスに依存しないMVCコントローラーで非同期を実行する新しい方法があります。
このサイトは役に立ち、さまざまなバージョンの.NetFrameworkのasp.netmvcで非同期操作を実行する方法を説明しています。
http://dotnet.dzone.com/news/net-zone-evolution