繁体   English   中英

MVC 5过滤器中的异步错误处理

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM