简体   繁体   中英

MVC Stream outputting to HTML div

Small problem here with an MVC app that I'm not sure how to figure out a way around.

Basically, I'm adding additional functionality to a system that was originally created by someone else (c#). For a reporting system, the results were only ever displayed on screen. Now I am building in the functionality to allow the user the ability to download their report as an Excel document.

So basically, I have a view that displays the date ranges, and some other search refinement options to the user. I have introduced a radio button that if selected will download the report as opposed to displaying it on screen.

Here are my three actions within the ReportController:

    public ActionResult Index()
    {
        return View();
    }


    public ActionResult ProductReport(AdminReportRequest reportRequest, FormCollection formVariables)
    {
        AdminEngine re = new AdminEngine();

        if (!reportRequest.Download)
        {
            AdminReport report = re.GetCompleteAdminReport(reportRequest);

            return View(report);
         }

            Stream ExcelReport = re.GetExcelAdminReport(reportRequest);
            TempData["excelReport"] = ExcelReport;

        return RedirectToAction("ExcelProductReport");

       }

    public FileResult ExcelReport()
    {
        var ExcelReport = TempData["excelReport"] as Stream;

        return new FileStreamResult(ExcelReport, "application/ms-excel")
        {
            FileDownloadName = "Report" + DateTime.Now.ToString("MMMM d, yyy") + ".xls"
        }; 
    } 

I've debugged through the AdminEngine, and everything looks fine. However, in the ExcelReport action, when it comes to returning the file - it doesn't. What I see is a lot of characters on screen (in the 'panelReport' div - see below), mixed in with what would be the data in the excel file.

I think I have established that the reason it is being displayed on screen is as a result of some code

that was written in the Index view:

<% using (Ajax.BeginForm("ProductReport", "Report", null,
                      new AjaxOptions
                      {
                          UpdateTargetId = "panelReport",
                          InsertionMode = InsertionMode.Replace,
                          OnSuccess = "pageLoaded",
                          OnBegin = "pageLoading",
                          OnFailure = "pageFailed",
                          LoadingElementId = ""
                      },
                      new { id = "SearchForm" })) %>

As you can see, the Ajax.BeginForm statement states that it should update to the panelReport div - which is what it's doing (through the Product Report partial view). While this is perfect for when the reports need to be displayed on screen, it is obviously not going to work with an excel file.

Is there a way of working around this issue without changing the existing code too much?

Here is the class where I do the workings for the excel file in case it's required to shed light on the situation:

Report Class:

public Stream GetExcelAdminReport(AdminReportRequest reportRequest)
{
        AdminReport report = new AdminReport();
        string dateRange = null;
        List<ProductSale> productSales = GetSortedListOfProducts(reportRequest, out dateRange);

        report.DateRange = dateRange;

        if (productSales.Count > 0)
        {
            report.HasData = true;

            CustomisedSalesReport CustSalesRep = new CustomisedSalesReport();

            Stream SalesReport = CustSalesRep.GenerateCustomisedSalesFile(productSales);

            return SalesReport;
        }
}

Workings Class:

public class CustomisedSalesReport
{
    public Stream GenerateCustomisedSalesFile(List<ProductSale> productSales)
    {
        MemoryStream ms = new MemoryStream();
        HSSFWorkbook templateWorkbook = new HSSFWorkbook();

        HSSFSheet sheet = templateWorkbook.CreateSheet("Sales Report");

        //Workings

        templateWorkbook.Write(ms);
        ms.Position = 0;

        return ms;
    }
} 

The problem is pretty obvious that you are using an Ajax Form to download a file. On top you are using the built-in Microsoft Ajax libraries, which seem to be not intelligent enough.

I can provide 2 solutions:

  1. The easiest solution (which I have used in the past) is that instead of streaming a file yourself, create an excel file and save it on the server and then send the download link to the user. It won't require a lot of change to the code.

  2. You could handle the OnSubmit event of the AjaxForm, see if you it's a file to download. If yes, then make a full postback request (using $.post() ). This way the browser will automatically pop-up the dialog asking for where to download.

Hope it makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM