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.
window.location
in success callback method. Here is the sample for you.