2009-12-31 31 views
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(); 
    } 

在此先感谢

+0

我试过了,但是一旦文件被返回,页面仍然显示div。我试过调用$ .unblockUI();当你从服务器回来时 – 2009-12-31 17:12:50

+0

我编辑了我的答案给出了更多的信息 – 2009-12-31 17:33:07

回答

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,但是从我的同事听到所有这些都应该可以在稍微调整之后进行。我希望它有帮助。

+0

我试过了,我会使用控制器的代码更新我的文章,也许会有帮助p – zSynopsis 2009-12-31 16:42:30

1

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

如果您有一个需要多秒执行的操作,那么您正在绑定ASP.NET工作线程来压缩站点的可伸缩性。这是为什么MVC 2 has AsyncControllers for delegating long-running tasks to a background thread。还有a workaround for MVC 1。您的行为不应写入Response。这样做会使操作变得不必要地难以测试,并且偏离标准MVC管道,其中像ViewResult这样的结果对象对Response进行实际写入。

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

例如,先从“在原始查看加载消息:

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

然后在准备好时加载,并更换‘正在加载...’与响应的内容:

$(document).ready(function() { 
    $("#report").load("/path/to/action"); 
}); 
+0

对不起,我仍然不明白。如果写入响应流是一个否定的,那么你会如何推荐我去返回生成的文件?我是mvc的新手,所以任何帮助将不胜感激。 – zSynopsis 2009-12-31 17:52:47

+0

一种方法是编写自定义结果类型。这里有一个示例:http://haacked.com/archive/2008/05/10/writing-a-custom-file-download-action-result-for-asp.net-mvc.aspx总的想法是,操作将数据传递给结果,并且结果更新响应。 – 2009-12-31 18:06:52