So I am working on a website page where the user selects some elements to make a specific report. I then have them click on a button, which makes an ajax call. This call (correctly) calls a method in the controller that creates a .csv file based off of the parameters.
However, the hard part is that, after I create this file, I want the user to download it in the usual manner-with the whole popup and putting it in the download folder and all that.
I found this stack overflow question that is more or less doing what I am now. Except it was written pre-ASP.NET Core, and it's not really working with my code. Here is my code right now:
<div class="mybutton">
<button type="button" class="btn btn-info" style="background-color:#587992" id="CreateExcel" onclick="CreateFile()"> Create an Excel File for this Data </button>
</div>
...
<script>
...
function CreateFile(){
array = getParameters();
$.ajax({
type: "POST",
data: { 'array': array },
cache: false,
traditional: true,
url: '@Url.Action("CreateCsvFile")',
success: function (data) {
if (data) {
var element = data;
window.location = 'Download?fileGuid=' + element.FileGuid
+ '&filename=' + element.FileName;
}
}
});
}
</script>
And then here is my controller code:
public ActionResult CreateCsvFile(string[] array)
{
List<OperatorInterventions> TempList = new List<OperatorInterventions>();
//Logic to apply the List to the passed in parameters in this line...
var memoryStream = new MemoryStream();
using (var writer = new StreamWriter(memoryStream, Encoding.UTF8, 1024, true))
using (var csv = new CsvWriter(writer))
{
csv.WriteRecords(TempList);
}
string handle = Guid.NewGuid().ToString();
memoryStream.Position = 0;
TempData[handle] = memoryStream.ToArray();
//return File(memoryStream, "text/csv", "clients.csv");
return new JsonResult(new { FileGuid = handle, FileName = "newreport.csv" });
}
[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{
if (TempData[fileGuid] != null)
{
byte[] data = TempData[fileGuid] as byte[];
return File(data, "text/csv", fileName);
}
else
{
// Problem - Log the error, generate a blank file,
// redirect to another controller action - whatever fits with your application
return new EmptyResult();
}
}
Right now, when I return from the Ajax call to CreateCsvFile, I attempt to handle data. When I step through the call, I can see that data/element contains something like "{"fileGuid":"0123","fileName":"newreport.csv"}"
, but in the URL call that window.location uses, it element.FileGuid and element.FileName end up being "undefined". I previously had JSON.parse(data)
in there, but that caused an error, and JSON.stringify(data)
did nothing.
Additionally, I suspect that even if I managed to get fileGuid and fileName to not be undefined in the url, I'm not totally sure if it would end up calling the Download file.
Is there a way to fix the undefined? Is there a better way to do this Ajax call-to-download in general?
Thanks