我正在从视图中点击一个按钮,从控制器生成并返回一个相当大的文件。 我希望能够做的是在生成文件时显示“生成文件”的叠加层,一旦完成,叠加层就会消失。 我将如何做这样的事情?
以下是我的控制器的示例。
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 :(得分: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中做过这些,但是根据我从同事那里听到的内容,经过一些调整之后,这一切都应该是可能的。我希望它有所帮助。
答案 1 :(得分:1)
用户界面是您遇到的问题中最少的。
如果您有一个需要几秒钟才能执行的操作,那么您将破坏ASP.NET工作线程以破坏站点的可伸缩性。这就是MVC 2 has AsyncController
s for delegating long-running tasks to a background thread的原因。还有a workaround for MVC 1。
此外,您的操作不应写入Response
。这样做会使操作不必要地难以测试,并偏离标准MVC管道,其中像ViewResult
这样的结果对象实际写入响应。
最后,当您准备好更新UI时,通常会通过回调来执行此操作。
,例如,在“原始视图中加载消息:
”开头<div id="report">Loading...</div>
然后加载就绪事件,并将“Loading ...”替换为响应内容:
$(document).ready(function() {
$("#report").load("/path/to/action");
});