I'm trying to pass an array/IEnumerable of Guids to a MVC 'GET' method that looks like this:
[HttpGet]
public ActionResult ZipResults(IEnumerable<Guid> ids)
{
using(var zip = new Zip())
{
foreach(var id in ids)
{
var stream = GetDataStream(id);
zip.AddEntry("filename.txt", stream);
}
}
var outputStream = new MemoryStream();
zip.Save(outputStream);
return FileStreamResult(outputStream, "application/octet-stream"){
FileDownloadName = "Results.zip" };
}
And my javascript looks like this:
$('the-button').click(function(){
// 1. Get the guids from a table and add to javascript array (works fine)
// 2. Grey-out screen and show processing indicator (works fine)
// 3. This is how I'm calling the "ZipResults" action:
$.ajax({
url: '@Url.Action("ZipResults", "TheController")',
type: 'GET',
data: $.toJSON({ ids: _ids }),
dataType: 'json',
contentType: 'application/json;charset=utf-8',
traditional: true,
success: function(){
// Undo the grey-out, and remove processing indicator
},
error: function(){
}
});
});
My expectation is that this will popup the download dialog on the browser. As it is, the javascript array being passed to the controller is null (on the server-side, it works correctly client-side). Also, this works fine with a 'POST', however, a 'POST' method used this way will not force the download dialog...
Open for suggestions :)
You should avoid sending JSON requests with GET. Try like this:
var _ids = [
'e2845bd4-9b3c-4342-bdd5-caa992450cb9',
'566ddb9d-4337-4ed7-b1b3-51ff227ca96c',
'25bc7095-a12b-4b30-aabe-1ee0ac199594'
];
$.ajax({
url: '@Url.Action("ZipResults", "TheController")',
type: 'GET',
data: { ids: _ids },
dataType: 'json',
traditional: true,
success: function() {
// Undo the grey-out, and remove processing indicator
},
error: function() {
}
});
This being said, I see that you are invoking some controller action which returns a file stream to download. You shouldn't be using AJAX at all to do this. The reason for that is that in your success callback you will get the contents of the ZIP file but there's not much you could do with it. You cannot save it to the client computer, you cannot prompt the user to choose a save location, you are pretty much busted.
So no AJAX calls if you want to download a file. You could use a simple anchor:
@Html.ActionLink("download zip", "ZipResults", "TheController", null, new { id = "download" })
and then:
$(function() {
$('#download').click(function() {
var _ids = [
'e2845bd4-9b3c-4342-bdd5-caa992450cb9',
'566ddb9d-4337-4ed7-b1b3-51ff227ca96c',
'25bc7095-a12b-4b30-aabe-1ee0ac199594'
];
var url = this.href;
for (var i = 0; i < _ids.length; i++) {
if (url.indexOf('?') > 0) {
url += '&ids=' + encodeURIComponent(_ids[i]);
} else {
url += '?ids=' + encodeURIComponent(_ids[i]);
}
}
window.location.href = url;
return false;
});
});
The problem is that a GET doesn't get a request body. I suspect that if you look at the client issued request, you would find that it is trying to shove an enumerable onto the query string....
Post -> Redirect seems like the best course of action here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With