0

I am using ASP.NET Core and ClosedXML to generate an Excel export.

Export Method 1

Here is the controller method that DOES return an .xlsx file to the browser. The method gets called from a .cshtml page:

<form id="downloadLoanEvents" asp-action="DownloadLoanEventsLog" asp-controller="Lender" asp-route-id="@Model.LoanFileId" method="post">
    <div class="form-group">
        <input type="submit" value="Submit" />
    </div>
</form>

This is the DownloadLoanEventsLog controller method:

[HttpPost]
public async Task<IActionResult> DownloadLoanEventsLog(string id)
{
    var user = await _userManager.GetUserAsync(HttpContext.User);
    var loan = _unitOfWork.LoanFiles.GetById(id);

    var list = eventLogService.GetLoanFileEventLog(id, _unitOfWork, user);
    string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    string fileName = $"Loan-{loan.LoanNumber}-EventsLog.xlsx";

    try
    {
        using (var workbook = new XLWorkbook())
        {
            IXLWorksheet worksheet = workbook.Worksheets.Add("Events");
            worksheet.Cell(1, 1).Value = "EventDate";
            worksheet.Cell(1, 2).Value = "LoanNumber";

            int index = 2;

            foreach (var row in list)
            {
                worksheet.Cell(index, 1).Value = row.EventDateTimeDisplay;
                worksheet.Cell(index, 2).Value = row.LoanNumber;
                index++;
            }

            using (var stream = new MemoryStream())
            {
                workbook.SaveAs(stream);
                var content = stream.ToArray();
                return File(content, contentType, fileName);
            }
        }
    }
    catch (Exception ex)
    {
        return RedirectToAction("CloseLoan", new { id = id }).WithWarning("", "Exporting Loan File Events Failed");
    }
    finally
    {
    }
}

The DownloadLoanEventLog method works great. I quickly get an expected Excel file to the browser.


Export Method 2

Here is the controller method that DOES NOT return an .xlsx file to the browser.

The method is nearly identical to the 1st method, but this export kicks off in Ajax call to send a json array of data to the controller.

var rows = $("#report").jqxGrid('getrows');

var loans = [];

for (var i = 0; i < rows.length; i++) {
    var row = rows[i];
    loans.push({
        "loanNumber": row.loanNumber,
        "loanType": row.loanType,
    });
}

var jqxhr = $.ajax({
    data: JSON.stringify(loans),
    contentType: "application/json",
    url: "/Reports/ExportLoansReport",
    type: "POST"
});

This is the ExportLoansReport controller method:

[HttpPost]
public IActionResult ExportLoansReport([FromBody] List<LoansReportExportViewModel> model)
{
    string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    string fileName = $"Loans-Export.xlsx";

    try
    {
        using (var workbook = new XLWorkbook())
        {
            IXLWorksheet worksheet = workbook.Worksheets.Add("Loans");
            worksheet.Cell(1, 1).Value = "LoanNumber";
            worksheet.Cell(1, 2).Value = "LoanType";
            
            int index = 2;

            foreach (var row in model)
            {
                worksheet.Cell(index, 1).Value = row.LoanNumber;
                worksheet.Cell(index, 2).Value = row.LoanType;
                
                index++;
            }

            using (var stream = new MemoryStream())
            {
                workbook.SaveAs(stream);
                var content = stream.ToArray();
                return File(content, contentType, fileName);
            }
        }
    }
    catch(Exception ex)
    {
        return Json("some fail msg");
    }
}

ExportLoansReport gets a valid json object in the [FromBody] parameter, and the code does not throw any exception at all. Once return File fires, nothing happens, no file is returned to the browser.

I suspect this issue is because the request was made from the client side but I am not sure how to fix it.

4
  • 1
    you ahve a missconception, both calls are made from the client side. look at the network tab in the browser developer tools. but basically you have your file in the variable you are using to store the response from the ajax call
    – Bloodday
    Commented Jun 27 at 1:44
  • Hey Bloodday, thanks for the comment. I will take a look at the network tab.
    – Ryan
    Commented Jun 27 at 1:59
  • If you want to download the files from browser by using ajax call, we have to using window.location in success callback method. Here is the sample for you.
    – Jason Pan
    Commented Jun 27 at 4:24
  • I still dont understand why Export Method 1 works and Export Method 2 does not. If both are made from the client side, why the difference in functionality?
    – Ryan
    Commented Jun 29 at 17:51

1 Answer 1

0

It seems that ajax itself is not designed to support downloading file scenarios. You might want to have a try with ajaxfiledownload package which supports fetching files from server in an asynchronous way.

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Jun 27 at 10:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.