0

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

Warbler
  • 71
  • 1
  • 2
  • 9
  • `FileGuid` !== `fileGuid` and similarly for `FileName` !== `fileName` - javascript is *case sensitive* about these things ... i.e. `window.location = 'Download?fileGuid=' + element.fileGuid + '&filename=' + element.fileName;` – Jaromanda X Aug 21 '19 at 22:29
  • `I'm not totally sure if it would end up calling the Download file` well, I know nothing about asp, but based on the code you have shown, it seems you may want `'@Url.Action("Download")?etc'` - given how your AJAX request is `'@Url.Action("CreateCsvFile")'` - again, total speculation on my part – Jaromanda X Aug 21 '19 at 22:31

1 Answers1

0

Since you could see the data as {"fileGuid":"0123","fileName":"newreport.csv"} using console.log(element) in ajax success, then you also need to use same key element.fileGuid instead of element.FileGuid:

success: function (data) {            
            if (data) {
                var element = data;
                console.log(element);
                window.location = 'Download?fileGuid=' + element.fileGuid
                       + '&fileName=' + element.fileName;
            }
        }
Ryan
  • 19,118
  • 10
  • 37
  • 53