【问题标题】:Ajax call to async method returning file successfully but success/complete part of an Ajax request is not getting executed对异步方法的 Ajax 调用成功返回文件,但 Ajax 请求的成功/完成部分未执行
【发布时间】:2020-05-22 23:14:31
【问题描述】:

我正在尝试将选定的记录导出到文件中并重新加载页面以更新当前视图中的记录。我正在异步调用 web api 来获取所有记录。 AJAX 调用正在控制器中成功执行操作并返回预期数据而没有任何错误,但没有执行 ajax 函数的“成功”、“完成”或“错误”部分。浏览器的开发人员工具没有错误,没有例外,没有什么不寻常的,所以对我来说进一步调查这个问题变得越来越棘手。我可以请您对此提出建议吗?谢谢

查看:

 @Html.ActionLink("Export records", "Index", null, new { Id = "myExportLinkId")

脚本:

        $("a#myExportLinkId").click(function (e) {
             var selected = "";
             $('input#myCheckBoxList').each(function () {
               if (this.checked == true) {
               selected += $(this).val() + ',';
               }
             });
             if (selected != "") {
                $.ajax({
                  url: '/MyController/MyAction',
                  type: 'GET',
                  contentType: "application/json; charset=utf-8",
                  dataType: "json",
                  data: {
                    'MyString': 'stringValue'
                  },
                  success: function (data) {
                    alert("success");
                  },
                  error: function () {
                    alert("error");
                  }
            });
          })

动作/方法如下所示:

    [HttpGet]
    public async Task<ActionResult> ExportNewOrders(string OrderIdString)
    {
      //code to create and store file 

      //actually want to send the file details as json/jsonResult but for testing only returning 
      //string here
      return Json( "Success", "application/json", JsonRequestBehavior.AllowGet);
    }

【问题讨论】:

  • 确定 ajax 调用正在发送到服务器吗?通过在网络选项卡中查看调用或在控制器方法中放置一个断点
  • 感谢您的重播@Sam。是的,它确实执行了控制器中的方法并成功返回了预期的结果,但执行没有达到 AJAX 调用的成功/完成/错误部分

标签: c# jquery ajax asynchronous model-view-controller


【解决方案1】:

最后,我通过 AJAX 调用的 Promisify 功能解决了这个问题。显然我返回的 json 响应有问题,所以我已经替换了

return Json( "Success", "application/json", JsonRequestBehavior.AllowGet);

 return new JsonResult(){
        Data = new { success = true, guid = handle, fileName = exportFileName },
        ContentType = "application/json",
        JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };

修复了bug,ajax调用成功函数被执行。

但除此之外,还有一些问题要等到文件下载(涉及加密解密、服务器验证等)完成然后刷新页面。我通过使用 Promisify 功能实现 ajax 调用解决了这个问题。您可以找到 codepen 示例 here 和原始帖子 here

这是完整的代码。

查看/HTML

@Html.ActionLink("Export", "yourActionName", null, new { Id = "exportRequest", @onclick = "letMeKnowMyFileIsDownloaded();" })

脚本/Ajax

        function letMeKnowMyFileIsDownloaded() {
        return new Promise(function (resolve, reject) {
            $("a#exportRequest").on("click", function () {
                    $.ajax({
                        url: this.href + "?param=whatever params you want to pass", 
                        dataType: "json",
                        data: {
                            'param1': 'value'
                        },
                        success: function (data) {
                            var a = document.createElement("a");
                            var url = '/yourControllerName/Download?fileGuid=' + data.guid + '&filename=' + data.fileName;//window.URL.createObjectURL(data);
                            a.href = url;
                            a.download = data.fileName;
                            document.body.append(a);
                            a.click();
                            a.remove();
                            window.URL.revokeObjectURL(url);
                            resolve(true);
                        },
                        error: function (error) {
                            reject(error);
                        }
                    });
            });
        });
    }

    letMeKnowMyFileIsDownloaded()
        .then(function (bool) {
            if (bool) {
                //alert("File downloaded ?");
                window.location.reload(1);
            }
        })
        .catch(function (error) {
            alert("error");
        });

我使用 nuget 包 ClosedXML 来处理 excel 文件功能。使用流创建和下载 excel 文件中的数据,无需将文件物理存储在服务器上。

在控制器中

//can be async or sync action
public async Task<ActionResult> Index(YourModel model)
{
    //do stuff you want

    var exportOrders = your_object;

    //using DataTable as datasource
    var dataSource = new DataTable();

    //write your own function to convert your_object to your_dataSource_type
    dataSource = FormatTypeToDataTable(exportOrders);

    if (dataSource != null && dataSource.Rows.Count > 0)
    {
        //install ClosedXML.Excel from nuget
        using (XLWorkbook wb = new XLWorkbook())
        {
            try
            {
                var handle = Guid.NewGuid().ToString();
                wb.Worksheets.Add(dataSource, "anyNameForSheet");
                string exportFileName = "yourFileName" + ".xlsx";
                MemoryStream stream = GetStream(wb);
                TempData[handle] = stream; exportFileName);
                return new JsonResult()
                {
                    Data = new { success = true, guid = handle, fileName = exportFileName },
                    ContentType = "application/json",
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
            catch (Exception ex)
            {
                //ModelState.AddModelError("", ex.Message);
            }
        }
    }
}

 public virtual ActionResult Download(string fileGuid, string fileName)
    {
        if (TempData[fileGuid] != null)
        {
            var stream = TempData[fileGuid] as MemoryStream;
            var data = stream.ToArray();
            return File(data, "application/vnd.ms-excel", fileName);
        }
        else
        {
            return new EmptyResult();
        }
    }

【讨论】:

    猜你喜欢
    • 2017-08-17
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多