MVC 4:操作执行时如何显示视觉反馈



我有一个动作(控制器操作),在某些情况下可能需要几分钟才能运行。我想为我们的用户提供视觉指示,表明该操作正在运行,例如消息,旋转器或进度栏。问题是,我很难弄清楚如何在行动完成的前端"检测"。

进行了一些研究后,我偶然发现了一篇文章,标题为"使用ASP.NET MVC 4中的异步方法"。它解释了异步操作和.NET任务的使用。它看起来像是好东西,我将花一些时间研究它,但是我对这个概念来说是个新的,无法真正了解它是否会给我我想要的东西。

所以,我对So社区的问题是,如果您在Yesnch的行动和任务方面有很多经验,这些问题是否会帮助我在执行操作时向用户提供视觉反馈?或者,我是从错误的步道开始吗?

编辑:

谢谢大家的回复。对不起,我延迟回到这个。发布此信息后,我意识到我弄错了这种情况。事实证明,我真正需要的是生成PDF然后将其返回到浏览器的文件,并在生成文件时向用户显示视觉指示器。

我认为,这是一个完全不同的问题。因此,我将其作为一个单独的问题发布。

使用异步控制器可以释放IIS请求线程,但它不会帮助您解决问题。如果您尚未关心许多长期运行的用户请求(足以饿死IIS请求池)。

如果您有传统的帖子,重定向,获取流程,则可以轻松地在帖子上显示一个旋转器,当浏览器响应并重定向到新页面时,它将消失。

如果您使用异步JavaScript,则可以在呼叫中显示旋转器并将其隐藏在完成处理程序中。

我建议您不要尝试从IIS启动自己的背景任务或线程,因为它可以随时回收您的应用域。通过用户请求,它通常会耗尽停止,但它不会知道您启动的任何其他背景任务。您可以在IIS上注册您的对象,因此它将首先在打算将您的应用程序域拆除之前通知您,但是您只能坚持30秒钟,然后IIS仍可以继续。由于您的工作通常需要更长的时间才能完成,因此我建议这条更复杂的路线可能对您效果不佳,并且会使您的代码更加复杂。

这确实取决于您的要求。让用户等待工作完成之前,他们可以继续使用您的应用程序,还是需要能够在等待工作完成?

时继续进行互动是可以的吗?

如果您可以让他们等待,请使用帖子,重定向,获取图案和您在提交时弹出的模态旋转器。

如果用户必须能够继续工作,则您将需要采取部分操作,而Ajax呼叫处理程序以显示和隐藏非模式的旋转器,以表明正在进行工作。

您可以简单地拥有一个页面,然后启动AJAX请求到您的操作。当您启动请求时,请显示一个旋转器。

然后,当Ajax请求成功或错误时,您将隐藏旋转器。

使用这种方法,您不需要使操作方法具有异步,因为您没有绑定UI。

这是我使用较长运行过程采用的方法的一个示例,以避免阻止UI线程并向用户提供视觉反馈。

我将用生成报告示例演示,这需要.NET 4.5。

围绕报告生成返回任务的报告的方法创建一种方法。

作为一个例子,请参见下面:

private Task RunReport() 
{
    return Task.Run(() => 
              // The below should contain your generate report code
              Thread.Sleep(5000)
     );
}

然后使您的Action返回任务并在调用报告之前放置await

这将解除UI线程,允许用户在生成报告时继续使用该站点。内容完成处理后将返回页面。

[HttpPost]
public async Task<ActionResult> RequestReportGen()
{
    await RunReport();
    // Add your link to the report in the content below
    return Content("Report generated!";
}

包括以下JavaScript库:

<script src="@Url.Content("~/Scripts/jquery-1.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

然后使用AJAX表单发布到您的方法中,请注意LoadingElementId(等待时显示)和UpdatedTargetId(显示完成的消息)。

 @using (Ajax.BeginForm("RequestReportGen", "Home", new AjaxOptions { UpdateTargetId = "result", LoadingElementId="loading" }))
 {
        <div id="loading" style="display:none;">Generating Report...</div>
        <div id="result"></div>
        <input type="submit" />
}

使用上述方法,您的用户仍然可以使用该站点,因为您的UI线程未被阻止,并且在加载和完成时将消息传达给用户。

最新更新