views:

151

answers:

1

I am returning File result from action triggered by the form post event. I can't get download dialog. Instead, if I use:

return File(Encoding.UTF8.GetBytes(reportPath), "text/plain", "Report.csv");

I get path to the file upon ajax execution in the target div.

When I use

return File(reportPath, "text/plain", "Report.csv");

I get content of the file in the target div.

The action is declared as

   [HttpPost]
   public virtual ActionResult ExportFilter(Model model) {
      string outputFile = CreateReport(model);
      return File(....)
   }

The form is submited via Ajax.BeginForm(...).

EDIT

A bit more info: My form has 2 submit buttons. One is used to present result in the target div, the other one is used to export the result. The actton is the same and I use this to determine which button triggered the event:

        [HttpPost]
        public virtual ActionResult Run( model )
        {
            var bExecute = !string.IsNullOrEmpty(Request.Form["execute"]);
            return bExecute ? Execute(model) : Export(model);
        }

        [HttpPost]
        public virtual ActionResult Execute( model )
        {
            ....
            return PartialView("Report", model); 
        }

       [HttpPost]
       public virtual FileResult Export( model ) {
                .....
               return File(....)
       }

After some answers I tried to redirect to Get action using :

   ....
    return RedirectToAction( MVC.Report.OfferDownload(ReportFile) );
}

    [HttpGet]
    public virtual FileResult OfferDownload(string FileName)
    {
        return File(FileName, "text/csv", "Report.csv");
    }

However, that didn't help.

I also tried to Stream file, but it didn't help too.

EDIT2

Definitely Ajax problem cuz it works when I replace Ajax.BeginForm with Html.BeginForm. One solution I have in mind is to use onclick event on submit buttons to change form attributes.

+1  A: 

Open the file located at the path supplied on the server and read it's contents. Send the contents down as the FileResult. Also, don't submit the form via AJAX if you are expecting a download. The response will be sent to the AJAX code and I don't think the browser will intercept it and give you a file download dialog. That actually might be the whole problem (in which case your second sample may work).

 string outputFile = CreateReport(model);
 using (var stream = new StreamReader( outputFile ))
 {
    return File( stream, "text/csv", "Report.csv" );
 }

EDIT: FWIW, I'd use "text/csv" or "application/csv" for a CSV file.

tvanfosson
Not submiting the form via Ajax is not an option for me. You see, the form is arranged in such way that it has 2 submit buttons - 1 displays results in target div via ajax, and the other one exports that result
majkinetor
What I would probably do is have the click handler for the export button do a normal submit (non-AJAX) and the other button do an AJAX submit. I would probably even have a separate action for the export. In fact, when I've done this, I usually have an action that handles any filter parameters and store the filter parameters in the session. That is the "form" is on the filter -- it gets posted via AJAX and updates the display. Export becomes a simple link at that point and uses the filter parameters (or defaults) to get the appropriate data and send it down as a file.
tvanfosson
Thanks. That looks like a good way to do it.
majkinetor