Inside my controller I am using ServiceStack.Text to serialize a List and wish to return it to the client.
I am passing json that gets passed and manipulated into a list of objects that I then want to return as a csv. I can confirm this part is working. The client reports the request was successful but no file is available for download. if i console.log the response it prints the csv string.
I actually receive a list of json strings that I deserialize and append to a single list.Again, I can confirm this is working as expected.
Here is the Code:
[ValidateInput(false)]
[HttpPost]
public FileContentResult DownloadCSV(List<string> json, string delimiter, string method)
{
var respCSV ="";
if (method == "combine")
{
List<AgmtToCSV> comb = new List<AgmtToCSV>();
foreach (var i in json)
{
var d = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AgmtToCSV>>(i);
foreach (var u in d)
{
comb.Add(u);
}
}
var csv = CsvSerializer.SerializeToCsv(comb);
respCSV = csv;
}
return File(new System.Text.UTF8Encoding().GetBytes(respCSV), "text/csv", "ExpirationReport.csv");
//return File(respCSV);
}
EDIT
Here is what the response look like:
Cache-Control:private
Content-Disposition:attachment; filename=ExpirationReport.csv
Content-Encoding:gzip
Content-Length:3117
Content-Type:text/csv
Date:Thu, 20 Jul 2017 17:42:16 GMT
Server:Microsoft-IIS/8.0
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:5.2
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?SDpcZGV2ZWxvcG1lbnRcQWdyZWVtZW50LVZpZXdlclxBViAxLjEuMyBkZXZcQVZcQVZcSG9tZVxEb3dubG9hZENTVg==?=
Here is the jquery request and how it handles the successful response..
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
console.log(r);
});
UPDATE - Solution
Was able to get this to work with the accepted answer: The success function was the key here. It creates a link that points to the download and then initiates it.
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
var converted = r;
document.body.appendChild(link);
var csv = converted;
blob = new Blob([csv], { type: 'text/csv' });
window.URL = window.URL || window.webkitURL;
var csvUrl = window.URL.createObjectURL(blob);
var filename = 'ExpirationReport.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
{
window.navigator.msSaveOrOpenBlob(blob, filename);
}
else {
$('#lnkDwnldLnk')[0].click();
}
document.body.removeChild(link);
});
return Fileline. However, including the filename parameter should set the Content-Disposition toattachment(i.e. a download), so there's nothing wrong with the code you have currently. Given that you have commented return that would actually return inline, are you sure that you have rebuilt your solution since you made this change?@Html.ActionLink()- your page will not reload if all you do is file download.