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

时间:2014-06-05 23:22:33

标签: c# asp.net-mvc wcf asynchronous task

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

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

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

我设置了一个友好的错误消息,适用于sync个动作,但不适用于async个动作。即使异常可能发生在不同的级别,操作也会继续运行。我尝试将AsyncTimeout属性应用于控制器操作,但没有运气,页面只是长时间加载。

我在代码中如何处理此问题的任何想法,最好是在全局类型级别,并在async控制器操作出现问题时将用户引导到错误页面?

2 个答案:

答案 0 :(得分:4)

方法#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

覆盖Async Controller的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);
}

答案 1 :(得分:2)

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

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

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(非推荐)来捕捉异常&amp;重定向到所需的操作,如:

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");
    }
}