Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Tuesday, February 27, 2018 3:20 PM
Hi,
I have a button on my razor view, it calls a method of controller which generate a excel sheet, it works fine. to make the long story short, here are some codes:
<button name="button" value="Generate" id ="btnGetData" class="btn btn-primary">@GlobalRes.GenerateReport</button>
public ActionResult Generate(string button, ReportViewModel viewModel, List<string> chooseRight, string wildCardProdType)
{
if (button == "Generate")
{
MemoryStream output = _reportService.GenerateReport1(viewModel, chooseRight, wildCardProdType);
return File(output.ToArray(),"application/vnd.ms-excel","Excel_Report.xls");
}
But, if I changes the above codes to be called through ajax as this, from debug, I can see the MemoryStream output data, but the excel file doesn't show up. I can see the alert("s") showing up, which means the ajax returns success result. but the excel file doesnot show up. Does anybody know why? Thanks
.....
$.ajax({
method: "POST",
url: '@Url.Action("Generate", "Report")',
data: { button: button1, viewModel: viewModel, chooseRight: listName, wildCardProdType: wildcardprodtype },
success: function () {
alert("s");
},
error: function () {
alert("e");
}
All replies (8)
Wednesday, February 28, 2018 1:05 AM ✅Answered
you need to write code to display the results. in the success routine byeArray is a binary array containing the file bytes. you will need to write javascript code to display the results. From your comments, you want the browser to do this with writing an excel viewer. In which case you can not use ajax.
why the browser displays an excel file.
1) the browser is navigated to the url, which returns file with the excel content type.
2) it looks for browser plugin thats registered to display the file content type
3) it loads the plug-in and passes the url to the plugin
4) the plug-in fetches the file by the passed url. usually the file will be in the browser file caches, so second fetch is not required
5) the plug-in display the file.
Wednesday, February 28, 2018 5:57 AM ✅Answered
Hi Peter Cong,
We can't directly return a file for download via an AJAX call. We can't have an AJAX request open the download prompt since we physically have to navigate to the file to prompt for download. So, we should call it by submitting the form or window.location.href.
$("#btnGetData").click(function () {
$("form").submit();
//Or
window.location.href ='@Url.Action("Generate","Report",new {button= "Generate"})';
}
If you still want ajax, use the window.location.href in success event:
success: function (data) {
alert("success");
window.location.href ='@Url.Action("Generate","Report",new {button= "Generate"})';
}
Best Regards,
Daisy
Tuesday, February 27, 2018 4:08 PM
change the success
// first setup $.ajax to support binary data:
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
if (settings.dataType === 'binary') {
settings.xhr().responseType = 'arraybuffer';
}
}
});
// get binary data
$.ajax({
method: "POST",
url: '@Url.Action("Generate", "Report")',
data: { button: button1, viewModel: viewModel, chooseRight: listName, wildCardProdType: wildcardprodtype },
dataType: 'binary',
success: function (byteArray) {
alert(byteArray);
},
});
Tuesday, February 27, 2018 5:09 PM
Hi,
And it doesn't do what you want when not called using Ajax? If done using a full postback the browser should see the content-disposition, knowing then this content should be downloaded rather than replacing the current content and trigger the download dialog. It should just work.
If using Ajax YOU get the result back programmatically and are in charge of doing something with the response. Likely something like turning the content into a data url or something similar (never tried as I didn't saw for now a huge benefit compared with letting the browser to handle that). Do you have to use Ajax ?
Edit: try perhaps https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post for a discussion about possible solutions.
Tuesday, February 27, 2018 6:20 PM
Hi,
And it doesn't do what you want when not called using Ajax? If done using a full postback the browser should see the content-disposition, knowing then this content should be downloaded rather than replacing the current content and trigger the download dialog. It should just work.
If using Ajax YOU get the result back programmatically and are in charge of doing something with the response. Likely something like turning the content into a data url or something similar (never tried as I didn't saw for now a huge benefit compared with letting the browser to handle that). Do you have to use Ajax ?
Edit: try perhaps https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post for a discussion about possible solutions.
Hi PatriceSc, As I mentioned in my original post, the method of controller is doing what I wanted when not called using Ajax, basically, the controller method filters the database and get dataset then dump the data to Excel sheet and showing up.
But the excel sheet does not show up when I switch the call through Ajax call, from debug, I can see the output data which is same, but the excel sheet does not show up. The reason I want to try ajax is that I want to compare the performance, and want to use Ajax call if I can get a better performance in terms of speed etc.
Tuesday, February 27, 2018 6:38 PM
change the success
// first setup $.ajax to support binary data:
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
if (settings.dataType === 'binary') {
settings.xhr().responseType = 'arraybuffer';
}
}
});
// get binary data
$.ajax({
method: "POST",
url: '@Url.Action("Generate", "Report")',
data: { button: button1, viewModel: viewModel, chooseRight: listName, wildCardProdType: wildcardprodtype },
dataType: 'binary',
success: function (byteArray) {
alert(byteArray);
},
});
Hi Bruce, Thanks a lot for your quick response, I have just tried your codes, it still doesnot work, the Excel sheet still does not show up.
I did get alert(byteArray) popup window, but there is not data in it, it is blank popup window.
Same as I mentioned before,
MemoryStream output = _reportService.GenerateReport1(viewModel, chooseRight, wildCardProdType);
return File(output.ToArray(),"application/vnd.ms-excel","Excel_Report.xls");
I did get the data of "output" as above, but it seems the return File(...) is failed when it returns to Success of ajax, is that any thing wrong with my implementation of your codes? thanks a lot,
Wednesday, February 28, 2018 12:10 PM
you need to write code to display the results. in the success routine byeArray is a binary array containing the file bytes. you will need to write javascript code to display the results. From your comments, you want the browser to do this with writing an excel viewer. In which case you can not use ajax.
why the browser displays an excel file.
1) the browser is navigated to the url, which returns file with the excel content type.
2) it looks for browser plugin thats registered to display the file content type
3) it loads the plug-in and passes the url to the plugin
4) the plug-in fetches the file by the passed url. usually the file will be in the browser file caches, so second fetch is not required
5) the plug-in display the file.
Hi Bruce, thank you so much for your confirmation, if this is the case, then I will not use ajax for this circumstance, as I can achieve it using submit form with a button option, so will not use ajax call for this case, the main purpose is to compare the performance between form submit and ajax call.
Any way, thank you so much for your help,
Wednesday, February 28, 2018 12:10 PM
Hi Peter Cong,
We can't directly return a file for download via an AJAX call. We can't have an AJAX request open the download prompt since we physically have to navigate to the file to prompt for download. So, we should call it by submitting the form or window.location.href.
$("#btnGetData").click(function () {
$("form").submit();
//Or
window.location.href ='@Url.Action("Generate","Report",new {button= "Generate"})';
}
If you still want ajax, use the window.location.href in success event:
success: function (data) {
alert("success");
window.location.href ='@Url.Action("Generate","Report",new {button= "Generate"})';
}
Best Regards,
Daisy
Hi Daisy, thank you so much for your confirmation, if this is the case, then I will not use ajax for this circumstance, as I can achieve it using submit form with a button option, so will not use ajax call for this case, the main purpose is to compare the performance between form submit and ajax call.
Any way, thank you so much for your help,