异步控制器操作中发生错误时重定向用户
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 模板已经为您的应用程序注册了一个全局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
(不推荐)捕获异常并重定向到所需的操作,例如:
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");
【讨论】:
以上是关于异步控制器操作中发生错误时重定向用户的主要内容,如果未能解决你的问题,请参考以下文章