0

我目前正在从视图中单击按钮从控制器生成并返回一个相当大的文件。我想做的是在生成文件时显示一个覆盖层,说明“正在生成文件”,一旦完成,覆盖层就会消失。我将如何去做这样的事情?

这是我的控制器的示例。

  public ActionResult Generate(FormViewModel fvm)
  {
        var isValid = AreInputsValid(fvm);
        if (!isValid)
        {
            TryUpdateModel(fvm);
            return View("Index", );
        }
        RenderReport(new Report(fvm));
        return View();
    }

    private void RenderReport(Models.Report report)
    {
        var localReport = new LocalReport { ReportPath = report.ReportPath };

        var reportDataSource = new ReportDataSource(report.DataSourceName, report.Model);
        localReport.DataSources.Add(reportDataSource);

        var reportType = "PDF";
        string mimeType;
        string encoding;
        string fileNameExtension;

        //The DeviceInfo settings should be changed based on the reportType
        //http://msdn2.microsoft.com/en-us/library/ms155397.aspx
        var deviceInfo =
            string.Format("<DeviceInfo><OutputFormat>{0}</OutputFormat><PageWidth>11in</PageWidth><PageHeight>8.5in</PageHeight><MarginTop>0.5in</MarginTop><MarginLeft>0.25in</MarginLeft><MarginRight>0.25in</MarginRight><MarginBottom>0.5in</MarginBottom></DeviceInfo>", reportType);

        Warning[] warnings;
        string[] streams;

        //Render the report
        var renderedBytes = localReport.Render(
            reportType,
            deviceInfo,
            out mimeType,
            out encoding,
            out fileNameExtension,
            out streams,
            out warnings);

        //Clear the response stream and write the bytes to the outputstream
        //Set content-disposition to "attachment" so that user is prompted to take an action
        //on the file (open or save)
        Response.Clear();
        Response.ContentType = mimeType;
        Response.AddHeader("content-disposition", "attachment; filename=" + report.ReportName + "." + fileNameExtension);
        Response.BinaryWrite(renderedBytes);
        Response.End();
    }

提前致谢

4

2 回答 2

1

用户界面是这里最少的问题。

如果您有一个需要几秒钟才能执行的操作,那么您就是在占用 ASP.NET 工作线程,从而破坏了您网站的可伸缩性。这就是为什么MVC 2 有AsyncControllers 用于将长时间运行的任务委托给后台线程MVC 1还有一个解决方法。

此外,您的操作不应写入Response. 这样做会使操作不必要地难以测试,并偏离标准 MVC 管道,其中结果对象就像ViewResult实际写入响应一样。

最后,当您准备好更新 UI 时,您通常会使用回调来执行此操作。

例如,从原始视图中的“加载消息”开始:

<div id="report">Loading...</div>

然后在ready事件中加载,并将“Loading...”替换为响应的内容:

$(document).ready(function() {
    $("#report").load("/path/to/action");
});
于 2009-12-31T17:35:47.400 回答
1

我会使用 jquery blockUI来显示叠加层,并在 div 中显示您的“生成文件”消息。您可以弹出这个 onClientClick ,它会一直保留到您从服务器返回

我总是将这段代码放在我使用 blockUI 的页面上。当出于某种原因您必须从服务器返回并显示模态时,它会很有帮助,否则它将隐藏以前可见的模态。

function pageLoad(event, args)
{
    var hdf = $('[id$=hdf_DisplayModal]').val();

    if(hdf != "")
        showPopup(hdf);
    else
        $.unblockUI();
}

然后我有一个附加的外部 jasvascript 文件,其中包含以下内容:

function showPopup(modal)
{
    showPopup(modal, null);
}

function showPopup(modal, fadeInTime)
{
    if(fadeInTime == null)
        fadeInTime = 500;

    modal = $('[id$=' + modal + ']');
    $.blockUI({ message: modal,
        fadeIn : fadeInTime,
        css: {
            top:  ($(window).height() - modal.height())/2  + 'px', 
            left: ($(window).width() - modal.width()) /2 + 'px', 
            width: modal.width() + 'px'
        }
    });
}

function closePopup(modal)
{
    closePopup(modal, null);
}

function closePopup(modal, fadeOutTime)
{
    $('[id$=hdf_DisplayModal]').attr("value", "");
    modal = $('[id$=' + modal + ']')
    $.unblockUI({ message: modal,
        fadeOut: fadeOutTime
    });
}

现在我从来没有在 MVC 中做过任何这样的事情,但是根据我从同事那里听到的消息,经过一点调整,这一切都应该是可能的。我希望它有所帮助。

于 2009-12-31T16:18:22.813 回答