【问题标题】:MVC4 Async Controller Action not completedMVC4 异步控制器操作未完成
【发布时间】:2013-09-19 12:34:44
【问题描述】:

我有一个被 jquery ajax 请求调用的异步操作:

查看:

$.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 没有异步运行。我希望它能够正常工作,以便如果已经调用了控制器操作并等待来自 web 服务的响应,我仍然应该能够简单地浏览离开我正在调用该操作的页面。

【问题讨论】:

  • 可以在 beforeSend 事件上显示 ajax 加载面板,并使用 complete 事件隐藏面板

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


【解决方案1】:

处理这种情况并简单地中止呼叫等的最佳方法是什么

您可以在开始 AJAX 请求之前订阅onbeforeunload 事件:

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

当 AJAX 调用完成时,移除对该事件的订阅。

【讨论】:

    【解决方案2】:

    既然你有一个AsyncTimeout 属性,你应该take a CancellationToken that represents that timeout

    还有另一个 CancellationToken 代表用户提前断开连接 (Response.ClientDisconnectedToken)。但是,有currently a race condition on ClientDisconnectedToken,所以我不建议在当前版本的 ASP.NET (4.5) 中使用它。目前最好的策略是尊重AsyncTimeout,而忽略早期的客户端断开连接。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多