MVC4异步控制器操作未完成

时间:2013-09-19 12:34:45

标签: c# asp.net asp.net-mvc asp.net-mvc-4

我有一个由jquery ajax请求调用的异步Action:

查看:

$.ajax({
    url: "@Url.Action("StartVerification", "Devices")",
    global: false,
    data: JSON.stringify(machineIds),
    contentType: 'application/json',
    type: 'POST'
    ...

控制器:

[HttpPost]
[SessionExpireFilter(Order = 1)]
[CheckPermissions(Order = 2)]
[AjaxMessagesFilter(Order = 3)]
[AsyncTimeout(30000, Order = 4)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimeoutError", Order = 5)]
public async Task<JsonResult> StartVerification(ICollection<Machine> machines)
{
    Dictionary<int, bool> collection = new Dictionary<int, bool>();
    foreach (var machine in machines)
    {
        Response response = new Response();
        try
        {
            response = await this.deviceRepository.StartVerification(machine);
        }
        catch (Exception ex)
        {
            response.Success = false;
        }
        collection.Add(machine.MachineID, response.Success);
    }

    return this.Json(collection.ToDictionary(x => x.Key.ToString(), y => y.Value));
}

网络服务电话:

public async Task<Response> StartVerification(Machine machine, CancellationToken cancelToken = default(CancellationToken))
{
    WebService WebServiceForTask = WebServiceFactory.NewInstance;

    return await Task.Run(() => WebServiceForTask.StartVerificationForWebSite(machine.SiteID, machine.MachineID));
}

我遇到的问题是,当执行StartVerification操作时,调用然后查询Web服务。对该结果的查询可能需要几秒钟,在此期间用户可以按下其浏览器的刷新按钮。什么是处理这种情况的最佳方式,只是中止呼叫等。

编辑: 也许我问这个问题错了。这里的问题是,当我在StartVerification并点击刷新页面F5时,页面将不会刷新,直到我从webservice获得响应...并且看起来Action不会运行异步。我希望它能够工作,这样如果已经调用了一个控制器动作并等待来自webservice的响应,我仍然可以简单地从我正在调用该动作的页面中进行浏览。

2 个答案:

答案 0 :(得分:1)

  

处理此方案的最佳方法是什么,只是中止呼叫等

您可以在启动AJAX请求之前订阅onbeforeunload事件:

window.onbeforeunload = function() {
    return 'There\'s an ongoing operation. If you leave this page you might lose some data';
};

当AJAX调用完成后,删除对此事件的订阅。

答案 1 :(得分:1)

由于您拥有AsyncTimeout属性,因此您应该take a CancellationToken that represents that timeout

还有另一个CancellationToken表示用户提前断开连接(Response.ClientDisconnectedToken)。但是,有currently a race condition on ClientDisconnectedToken因此我不建议将其与当前版本的ASP.NET(4.5)一起使用。现在最好的策略是尊重AsyncTimeout并忽略早期客户端断开连接。

但是,如果您确实想要检测客户端断开连接,则可以定期轮询Response.IsClientConnected