简体   繁体   English

Ajax 调用异步方法成功返回文件,但未执行 Ajax 请求的成功/完成部分

[英]Ajax call to async method returning file successfully but success/complete part of an Ajax request is not getting executed

I am trying to export selected records in to a file and reload the page to update the records in a current view.我正在尝试将选定的记录导出到文件中并重新加载页面以更新当前视图中的记录。 I am calling web api asynchronously to get all the records.我正在异步调用 web api 以获取所有记录。 An AJAX call is executing an action in a controller successfully and returning expected data without any error but none of the 'success', 'complete' or 'error' part of ajax function is executing. An AJAX call is executing an action in a controller successfully and returning expected data without any error but none of the 'success', 'complete' or 'error' part of ajax function is executing. There are no errors in a developer tool of the browser, no exception, nothing unusual so its getting trickier for me to investigate this issue further.浏览器的开发人员工具没有错误,没有例外,没有什么不寻常的,所以对我来说进一步调查这个问题变得越来越棘手。 Can I request your a suggestions on this please?我可以请您对此提出建议吗? Thanks谢谢

View:看法:

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

Script:脚本:

        $("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");
                  }
            });
          })

And the action/method looks like this:动作/方法如下所示:

    [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);
    }

Finally I have resolved this with Promisify functionality of an AJAX call.最后,我通过 AJAX 调用的 Promisify 功能解决了这个问题。 Obviously the json response I was returning had an issue so I have replaced显然,我返回的 json 响应有问题,所以我已更换

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

to

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

which has fixed the bug and the success function of ajax call got executed.它已修复该错误并成功执行 ajax 调用的 function 调用。

But other than this there were issues to wait until the file download (which involved encryption decryption, server validations etc) completes and then refresh the page.但除此之外,还有一些问题要等到文件下载(涉及加密解密、服务器验证等)完成然后刷新页面。 This I have resolved by implementing an ajax call with Promisify fuctionality.我通过实现具有 Promisify 功能的 ajax 调用解决了这个问题。 You can find codepen example here and the original post here .您可以在此处找到 codepen 示例,并在此处找到原始帖子。

Here is the complete code.这是完整的代码。

View/HTML查看/HTML

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

Script/Ajax脚本/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");
        });

I have used nuget package ClosedXML to handle excel file functionality.我已经使用 nuget package ClosedXML 来处理 excel 文件功能。 Using the stream to create and download the data in excel file without storing the file physically on the server.使用 stream 创建和下载 excel 文件中的数据,无需将文件物理存储在服务器上。

And in the controller并在 controller

//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();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM