异步控制器操作中发生错误时重定向用户

Posted

技术标签:

【中文标题】异步控制器操作中发生错误时重定向用户【英文标题】:Redirect user when error occurs in async controller action 【发布时间】:2014-07-27 03:09:48 【问题描述】:

我有一个 ASP.NET MVC 4 Web 应用程序,它通过 WCF 服务从数据源检索数据。

我已将大多数控制器设置为Async,后续方法设置为基于Task

我遇到了一个问题。如果我的代码中发生异常,则正在加载的页面将继续加载并最终超时并显示 IIS 错误页面。

我设置了一条友好的错误消息,并且对于 sync 操作可以正常工作,但对于 async 操作则不行。即使异常可能发生在不同的级别,该操作仍会继续运行。我尝试将AsyncTimeout 属性应用于控制器操作,但没有成功,页面只是长时间加载。

有什么想法可以在我的代码中处理这个问题,最好是在全局类型级别,并在 async 控制器操作出现问题时将用户引导到错误页面?

【问题讨论】:

【参考方案1】:

方法#1

在 Web.config 中将 customErrors 设置为 On 或 RemoteOnly

<system.web>
    <customErrors mode="On" />
</system.web>

在自定义错误视图中使用 HandleErrorAttribute

[AsyncTimeout(1000)]
[HandleError(ExceptionType=typeof(System.TimeoutException), View="Timeout")]
public async Task<ActionResult> AsyncActionResultReport()


方法#2

覆盖异步控制器的 OnException 方法,或使用自定义异常属性

public override void OnException(ExceptionContext filterContext)

    if(filterContext.Exception is TimeoutException && filterContext.Controller is AsyncController)
    
        filterContext.HttpContext.Response.StatusCode = 200;
        filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary 
                     "Controller", "Home" ,
                     "Action", "TimeoutRedirect" 
        filterContext.ExceptionHandled = true;
    

    base.OnException(filterContext);

【讨论】:

【参考方案2】:

如果你想做控制器级别,Dave A 建议的HandleError 是完美的。但是要在全局级别应用 HandleError 属性,您必须使用 ExceptionFilter

您还可以通过将HandleError 属性注册为全局错误处理程序,将其应用于整个应用程序。要注册全局错误处理程序,请打开 App_Start 文件夹中的 FilterConfig.cs 文件以找到 RegisterGlobalFilters 方法。 默认情况下,ASP.NET MVC 模板已经为您的应用程序注册了一个全局HandleErrorAttributeGlobalFilterCollection。在这里,您还可以将自己的自定义过滤器添加到全局过滤器集合中,例如:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

  filters.Add(new HandleErrorAttribute
  
    ExceptionType = typeof(System.TimeoutException),
    View = "TimeoutExceptionView"
  );

  filters.Add(new HandleErrorAttribute()); //by default added

详情参考:

http://www.dotnet-tricks.com/Tutorial/mvc/19D9140313-Exception-or-Error-Handling-and-Logging-in-MVC4.html

或者您可以使用Application_Error(不推荐)捕获异常并重定向到所需的操作,例如:

protected void Application_Error(object sender, EventArgs e)

    Exception exception = Server.GetLastError();
    System.Diagnostics.Debug.WriteLine(exception);
    if (exc.GetType() == typeof(TimeoutException)
    
      Response.Redirect("/Home/ErrorView");
    

【讨论】:

以上是关于异步控制器操作中发生错误时重定向用户的主要内容,如果未能解决你的问题,请参考以下文章

Sentry 捕获错误时重定向到新页面

容器在启动时重定向日志文件的方法

Grails 和 Spring Security 插件:基于角色登录时重定向用户

根据地理位置在首次访问时重定向用户

提交表单时重定向到错误的路线

处理asp.net核心中的异常?