【发布时间】:2016-03-16 01:36:36
【问题描述】:
我想在中间件组件中连接异常处理,如下所示:
public override async Task Invoke(IOwinContext context)
{
try
{
await Next.Invoke(context);
}
catch (Exception ex)
{
// Log error and return 500 response
}
}
但是,我想捕获的一些异常正在被 Web API 管道捕获并转换为HttpErrorResponses,然后我才能找到它们。在此过程中,我丢失了很多有关错误的详细信息,因此在调试等时无法获得有用的堆栈跟踪(调试器甚至在抛出异常时都不会停止 - 我必须手动单步执行代码并查看它失败的地方......)。
我尝试使用以下实现添加自定义异常处理程序:
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var owinContext = context.Request.GetOwinContext();
owinContext.Set(Constants.ContextKeys.Exception, context.Exception);
return Task.FromResult(0);
}
在我的启动配置中通过config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());注册,但是通过Next.Invoke(context)执行后查看
context.Get<Exception>(Constants.ContextKeys.Exception);
仍然没有给我我想要的所有细节,也没有在调试器的故障点处停止。
有没有办法可以完全关闭所有内置错误处理,以便我自己的中间件可以处理?
澄清,因为很多人似乎误解了我所追求的:
- Web API 中的内置错误处理捕获一些(但不是全部)异常并将它们重写为 500 个响应。
- 我想捕获所有异常,做一些日志记录,然后然后发出 500 个响应我选择的信息(对于大多数,请参阅下一个项目符号)。
- 还有一些异常表示业务逻辑错误,我想为此返回 40x 错误。
- 我希望它位于(应用程序)管道的顶部,即在请求生命周期中包装 所有内容
- 我想使用 OWIN 处理此问题,以使其可移植到未来可能的自托管方案(即,此应用程序将始终托管在 IIS 上并不是一成不变的 - HTTP 模块、Global.asax.cs 等在这里不相关)。
【问题讨论】:
-
“抛出异常时调试器甚至不会停止”-您是否在 VS 中尝试过,Debug->Exception... 然后为所有异常选择检查“Thrown”。这将导致调试器在每次抛出异常时停止。
-
@lcryder:是的,但这仍然不能满足我的所有需求。例如,它也会在我确实在其他地方处理的异常上停止调试器,从而从不首先传播到中间件。
-
您到底想对这些错误做什么?它纯粹是为了记录目的吗?如果是这样,那么 HTTP 模块可能是合适的,而且实现起来非常简单。
-
@DavidG:不,它既记录了日志,又给出了适当的响应。 HTTP 模块以与中间件相同的方式解决问题(但使用不同的管道,即不严格相关)。 Web API 已经将异常重写为 500 响应仍然存在问题,在中间件(或 HTTP 模块)到达之前丢弃了大量信息。
标签: c# asp.net asp.net-web-api owin