I have the following code:
Response.ClearContent();
Response.AddHeader( "Content-type", "application/vnd.ms-excel");
Response.AddHeader("content-disposition", "attachment;filename=test.xls");
Response.ContentType = "application/excel";
var swr = new StringWriter();
var tw = new HtmlTextWriter(swr);
grd.RenderControl(tw);
Response.Write(swr.ToString());
Response.Flush();
Response.End();
tw.Close();
swr.Close();
This action is triggered from the following bit of jquery code:
<img src="../../../../Content/images/Excel-icon.png"
onclick = "alert ($('#Filter').serialize());
$.ajax({
type: 'POST',
url: '<%=Url.Action( "Excel") %>',
data: $('#Filter').serialize(),
success : function (data, textStatus, jqXHR)
{ alert (data);},
error: function (jqXHR, textStatus, errorThrown)
{ alert (textStatus + ' ' + errorThrown);}
});" />
I have confirmed with fiddler that the headers have the expected values. I can also see the data in fiddler using the Web View.
Also, when I show the contents of data from the success function, it has the raw html for the table that I am trying to export to excel.
Thanks in advance for your help.
Oh, no, you cannot use AJAX to download files. The AJAX call is executed, the file is streamed to the client, your success callback is executed and passed the contents of the file that's where you will get stuck. For obvious security reasons you cannot do much with this data. You cannot save it to the client computer. You cannot show a prompt to Save As at this stage.
So remove your javascript AJAX call and invoke your controller action using a normal GET or POST request.
I would suggest not putting that code directly in an Action method -- that's not a very clean way to use MVC, and you certainly can't trigger a file download from an AJAX request.
You could derive a new action result -- call it ExcelResult
-- from the FileResult
class, an override its ExecuteResult
method to force the content into the Response
.
The button click should simply hit the action through a link (navigate to it). The response from the server and the browser will work together to force the file at a user without browsing to a new page.
Example:
public class ExcelResult : FileResult
{
public override void ExecuteResult(ControllerContext context)
{
string file;
using (var swr = new StringWriter())
{
using (var tw = new HtmlTextWriter(swr))
{
// Not sure where your grd object comes from
grd.RenderControl(tw);
file = swr.ToString();
}
}
var response = context.HttpContext.Response;
response.Buffer = true;
response.Clear();
response.ClearHeaders();
response.ContentType = "application/excel";
response.CacheControl = "public";
response.AddHeader("Pragma", "Public");
response.AddHeader("Expires", "0");
response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.AddHeader("Content-Description", "describe your file");
response.AddHeader("Content-Disposition","attachment; filename=excel.xls");
response.Write(file);
response.Flush();
response.End();
}
}
And your Action is simply:
public ExcelResult Excel()
{
return new ExcelResult(/* whatever you need to pass */);
}
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