[英]Asynchronous error handling in MVC 5 filters
我已经创建了一个自定义过滤器属性来扩展HandleErrorAttribute
,它捕获所有异常。
我的整个应用程序都是围绕整个堆栈中的异步架构构建的。 这意味着,我不得不异步使用OnException(ExceptionContext contect)
覆盖。 像这样的东西,就像我想象的那样(简化了可读性):
public async override void OnException(ExceptionContext context)
{
base.OnException(context);
var logId = await LogException(e, httpContext); //LogException calls an async method and returns the ID of the exception, after it has been saved to the database. I this ID in the filterContext, which is why I need the result of the method
}
但是,这将导致InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle
InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle
。
我不能简单地在同步调用时调用.Result,因为这会导致死锁。
所以我想我的问题是:如何在MVC5中创建一个可以异步记录错误的过滤器?
由于错误处理通常不是热代码,因此这里没有性能问题。 因此,做最方便的事情。
例如,您可以阻止从LogException
返回的任务。 有多种方法可以可靠地避免死锁。 一个简单的方法是Task.Run(() => LogException()).Wait();
。 这是因为任务主体在没有同步上下文的情况下运行。
您还可以在LogException
添加ConfigureAwait(false)
,但不能错过任何一个地方。 这使得这很脆弱。
我建议你改变方法并实现自己的ExceptionLogger,因为它是用于记录异常的ExceptionLogger作业
我们提供了两个新的用户可替换服务IExceptionLogger和IExceptionHandler来记录和处理未处理的异常。 服务非常相似,有两个主要区别:我们支持注册多个异常记录器,但只支持一个异常处理程序。 即使我们即将中止连接,也会始终调用异常记录器。 只有当我们仍然可以选择要发送的响应消息时,才会调用异常处理程序。 这两种服务都提供对异常上下文的访问,该异常上下文包含检测到异常的相关信息,特别是HttpRequestMessage,HttpRequestContext,抛出的异常和异常源。
这里是示例代码
public class ExceptionLogger : IExceptionLogger
{
public virtual Task LogAsync(ExceptionLoggerContext context,
CancellationToken cancellationToken)
{
return MyLogger.Log(context, cancellationToken);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.