1

I have a piece of javascript which sends through and array and an int.

var InvoicesAndId = { values: indexArray, Id:3 };

$.ajax({
type: "POST",
url: 'Invoice/Export',
data: postData,
success: function (data) {location.replace(window.location.pathname); },
dataType: "json",
tradional: true
});

So this calls the method on my Controller:

public void Export(InvoicesAndId invoicesAndId)
{
...

Response.AppendHeader("content-disposition", "attachment; filename" + "invoices.csv");
Response.ContentType = "application/ms-excel";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
Response.Write("word");
Response.End();
}

So with the debugger I've found that InvoicesAndId is populated correctly. The problem is a dialog is supposed to come up saying whether to open or save the excel file.

This doesn't happen.

I know this has something to do with how I'm calling the function because if I call it with an ActionLink the dialog appears.

What am I doing wrong? Is it something to do with the ajax call?

How to fix this? I can't use an ActionLink because there wouldn't probably be a way to populate the parameters.

AnonyMouse
  • 18,108
  • 26
  • 79
  • 131
  • I don't get it. Why did you change accepted answer? You question was not about MVC ActionResult, it's about javascript. Darin's answer is good, I also upvoted. Was my answer incorrect or unuseful? Am I missing something? – Emre Erkan Dec 06 '11 at 00:32

3 Answers3

3

What am I doing wrong?

In ASP.NET MVC you normally invoke controller actions which return ActionResult, they don't use Response.Write:

public ActionResult Export(InvoicesAndId invoicesAndId)
{
    Response.ContentType = "application/ms-excel";
    byte[] excel = Encoding.UTF8.GetBytes("word"); // Obviously not a valid Excel
    return File(excel, "application/ms-excel", "invoices.csv");
}

Now obviously setting content type to "application/ms-excel" and writing a simlpe string such as word to the response, don't expect to get anything but a corrupt Excel file. But I guess that was just an example that you will fix and write a real Excel file.

Or adjust your content type to CSV if this is what you intend to send:

Response.ContentType = "text/csv";

Now that's only the first part. The second part and the one that's actually at the root of your problem is that you are using AJAX to invoke this controller action. You cannot use AJAX to invoke controller actions that are supposed to download files. Simply because when you use AJAX to invoke such an action you end up in the success callback with the data javascript variable passed to it and containing the CSV file. Obviously since you are now on the client side you cannot do anything with it. For security reasons you cannot save it to the client nor prompt for download (it's already downloaded).

So you should use standard links or form submissions to invoke controller actions that are supposed to stream files to be downloaded.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
2

You don't have to use $.ajax, you can serialize your parameters with $.param() and set location to constructed url;

var InvoicesAndId = { values: indexArray, Id:3 };
location.href = 'Invoice/Export?' + $.param(InvoicesAndId, true);

This way, browser will try to navigate to new url, but because it returns a file, file open/save dialog will appear and user will not navigate to another url.

Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
0
public class ExcelResult : ActionResult
{
  public string FileName { get; set; }
  public string Path { get;set; }

  public override void ExecuteResult(ControllerContext context)
  {
        context.HttpContext.Response.Buffer = true;
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.AddHeader("content-disposition", "attachment;     filename=" + FileName);
        context.HttpContext.Response.ContentType = "application/vnd.ms-excel";
          context.HttpContext.Response.WriteFile(context.HttpContext.Server.MapPath(Path));   
  }
}

and

public ExcelResult GetExcelFile()
{  
    return new ExcelResult
              {
                    FileName = "sample.xls", Path = "~/Content/sample.xls"
              };
              }`
Ram Khumana
  • 844
  • 6
  • 14