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

时间:2020-12-31 02:20:21

I have an ASP.NET MVC 4 web application that retrieves data from a data source via WCF services.

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

I have set up most of controllers to be Async and subsequent methods to be Task based.

我已经将大多数控制器设置为Async,后续方法是基于任务的。

I have encountered a problem though. If an exception occurs in my code, the page being loaded just continues to load and in the end times-out with the IIS error page showing.

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

I have a friendly error message set up and works fine for sync actions but not async ones. The action just keeps running even though an exception may have occurred at a different level. I tried applying the AsyncTimeout attribute to the controller action but no luck, page just keeps loading for a long period of time.

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

Any ideas how I could handle this in my code, preferably at a global type level and direct the user to an error page when an issue occurs with an async controller action?

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

2 个解决方案

#1


4  

Approach #1

Set customErrors to On or RemoteOnly in Web.config

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

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

Use HandleErrorAttribute with custom error view

将HandleErrorAttribute与自定义错误视图一起使用

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

Approach #2

Override the OnException Method of your Async Controller, or use a custom Exception Attribute

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

#2


2  

If you want to do controller level, the HandleError as suggested by Dave A is perfect. But for applying HandleError Attribute at Global Level you have to use ExceptionFilter.

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

You can also apply the HandleError Attribute for the entire application by registering it as a global error handler. For registering a global error handler, open the FilterConfig.cs file with in App_Start folder to find the RegisterGlobalFilters method. By default, ASP.NET MVC template has already registered a global HandleErrorAttribute to the GlobalFilterCollection for your application. Here you can also add your own custom filter to the global filter collection as well like :

您还可以通过将HandleError属性注册为全局错误处理程序来为整个应用程序应用HandleError属性。要注册全局错误处理程序,请在App_Start文件夹中打开FilterConfig.cs文件以查找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
}

For details refer:

详情请参考:

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

OR

Alternatively you can use Application_Error(NOT Recommended) to catch exception & redirect to required action like:

或者,您可以使用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");
    }
}

#1


4  

Approach #1

Set customErrors to On or RemoteOnly in Web.config

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

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

Use HandleErrorAttribute with custom error view

将HandleErrorAttribute与自定义错误视图一起使用

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

Approach #2

Override the OnException Method of your Async Controller, or use a custom Exception Attribute

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

#2


2  

If you want to do controller level, the HandleError as suggested by Dave A is perfect. But for applying HandleError Attribute at Global Level you have to use ExceptionFilter.

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

You can also apply the HandleError Attribute for the entire application by registering it as a global error handler. For registering a global error handler, open the FilterConfig.cs file with in App_Start folder to find the RegisterGlobalFilters method. By default, ASP.NET MVC template has already registered a global HandleErrorAttribute to the GlobalFilterCollection for your application. Here you can also add your own custom filter to the global filter collection as well like :

您还可以通过将HandleError属性注册为全局错误处理程序来为整个应用程序应用HandleError属性。要注册全局错误处理程序,请在App_Start文件夹中打开FilterConfig.cs文件以查找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
}

For details refer:

详情请参考:

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

OR

Alternatively you can use Application_Error(NOT Recommended) to catch exception & redirect to required action like:

或者,您可以使用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");
    }
}