【问题标题】:MVC 4: How to display visual feedback while an Action executes?MVC 4:如何在 Action 执行时显示视觉反馈?
【发布时间】:2014-01-31 22:26:09
【问题描述】:

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

对此进行了一番研究后,我偶然发现了一篇题为“Using Asynchronous Methods in ASP.NET MVC 4”的文章。它解释了异步操作和 .NET 任务的使用。它看起来不错,我将花一些时间研究它,但我对这个概念还太陌生,无法真正理解它是否会给我想要的东西。

所以,我向 SO 社区提出的问题是,如果您在异步操作和任务方面拥有丰富的经验,这些是否可以帮助我在我的操作执行时向我的用户提供视觉反馈?或者,我是不是走错路了?

编辑:

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

在我看来,这是一个完全不同的问题。所以,我会把它作为一个单独的问题发布。

【问题讨论】:

  • 当您说Action 时,您是指控制器操作还是只是一些逻辑代码单元?
  • 我的意思是控制器动作。很抱歉造成混乱。

标签: asp.net-mvc asp.net-mvc-4 action execution user-feedback


【解决方案1】:

使用异步控制器会释放 IIS 请求线程,但不会帮助您解决问题。如果您不担心同时进入许多长时间运行的用户请求(足以使 IIS 请求池饿死),您可能不需要在这方面做太多研究。

如果您有传统的 Post、Redirect、Get 流程,您可以轻松地在 post 上显示一个微调器,当浏览器收到响应并重定向到新页面时该微调器会消失。

如果您使用的是异步 JavaScript,则可以在调用中显示微调器并将其隐藏在完成处理程序中。

我建议您不要尝试从 IIS 启动自己的后台任务或线程,因为它可以随时回收您的应用程序域。对于用户请求,它通常会停止,但它不会知道您启动的任何其他后台任务。您可以使用 IIS 注册您的对象,因此它会在打算拆除您的应用程序域之前首先通知您,但您最多只能推迟 30 秒,然后 IIS 将继续运行。由于您的工作通常需要比这更长的时间才能完成,因此我建议这种更复杂的路线可能不适合您,并且会使您的代码更加复杂。

这真的取决于您的要求。让用户在继续使用您的应用程序之前等待工作完成是否可以,或者他们是否需要在等待工作完成时继续进行交互?

如果您可以让他们等待,请使用 Post、Redirect、Get 模式和您在提交时弹出的模式微调器。

如果用户必须能够继续工作,您将需要 PartialResponse 操作和带有处理程序的 AJAX 调用来显示和隐藏非模态微调器以指示工作正在进行中。

【讨论】:

    【解决方案2】:

    您可以简单地创建一个页面,然后对您的操作启动 AJAX 请求。当您启动请求时,显示一个微调器。

    当 AJAX 请求成功或出错时,您将隐藏微调器。

    使用这种方法,您不需要将 Action 方法设置为异步的,因为您不会占用 UI。

    【讨论】:

      【解决方案3】:

      这是我采用较长运行进程以避免阻塞 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 线程不会被阻止,并且在加载和完成时会将消息转发回用户。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-16
        • 1970-01-01
        • 2014-09-21
        • 1970-01-01
        • 2020-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多