Вывод потока MVC в HTML div

#c# #asp.net-mvc #stream

#c# #asp.net-mvc #поток

Вопрос:

Небольшая проблема с приложением MVC, которую я не уверен, как найти способ обойти.

По сути, я добавляю дополнительные функциональные возможности в систему, которая изначально была создана кем-то другим (c #). Для системы отчетности результаты всегда отображались только на экране. Теперь я создаю функциональность, позволяющую пользователю загружать свой отчет в виде документа Excel.

Итак, в принципе, у меня есть представление, которое отображает диапазоны дат и некоторые другие параметры уточнения поиска для пользователя. Я ввел переключатель, который, если он выбран, будет загружать отчет, а не отображать его на экране.

Вот мои три действия в 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"
        }; 
    } 
  

Я отладил через AdminEngine, и все выглядит нормально. Однако в действии ExcelReport, когда дело доходит до возврата файла — этого не происходит. То, что я вижу, — это множество символов на экране (в div ‘panelReport’ — см. Ниже), смешанных с тем, что могло бы быть данными в файле Excel.

Я думаю, я установил, что причина, по которой он отображается на экране, является результатом некоторого кода

это было написано в индексном представлении:

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

Как вы можете видеть, в инструкции Ajax.BeginForm указано, что он должен обновиться до div panelReport, что он и делает (через частичный просмотр отчета о продукте). Хотя это идеально подходит для случаев, когда отчеты должны отображаться на экране, очевидно, что это не сработает с файлом Excel.

Есть ли способ обойти эту проблему, не слишком сильно изменяя существующий код?

Вот класс, в котором я выполняю обработку файла Excel на случай, если это потребуется, чтобы пролить свет на ситуацию:

Класс отчета:

 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;
        }
}
  

Рабочий класс:

 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;
    }
} 
  

Ответ №1:

Проблема довольно очевидна в том, что вы используете Ajax-форму для загрузки файла. Кроме того, вы используете встроенные библиотеки Microsoft Ajax, которые кажутся недостаточно интеллектуальными.

Я могу предоставить 2 решения:

  1. Самое простое решение (которое я использовал в прошлом) заключается в том, что вместо потоковой передачи файла самостоятельно создайте файл Excel и сохраните его на сервере, а затем отправьте ссылку на скачивание пользователю. Это не потребует больших изменений в коде.

  2. Вы могли бы обработать событие onSubmit ajaxForm, посмотреть, нужно ли загружать этот файл. Если да, то сделайте полный запрос обратной передачи (используя $.post() ). Таким образом, браузер автоматически выведет диалоговое окно с запросом, где загрузить.

Надеюсь, это имеет смысл.