在我们的应用程序中,我们有一组非常简单的日志记录挂钩(MVC和API控制器上的IExceptionFilters以及Application_Error()中的额外catch-all),但是有一整类错误不会触发任何错误。如果从WebAPI本身或内部使用的内容(例如由依赖项解析程序创建的类的初始化程序)中抛出异常,我得到的只是发送给客户端的500响应。
我发现捕获错误详细信息的唯一方法是使用HttpConfiguration.IncludeErrorDetailPolicy来配置应用程序以发出错误详细信息 - 但是,向世界广播您的错误详细信息是一个明显的不良做法,所以我会我希望完全关闭它,或者将其设置为有条件的(例如,仅限本地)。但是这意味着远程进入运行应用程序的服务器并使用可以检查响应的工具在本地调用API(如IE或谷歌浏览器),以了解发生了什么。
我已经在这里以类似的方式看到了另一个问题(here),但我们的想法是,使用DelegatingHandler检查响应的解决方案并不符合我们的需求。是否真的没有我可以挂钩的事件,我可以使用的扩展点,或类似的东西来捕获发生的实际异常?
(顺便说一下,我想我可以将IncludeErrorDetailPolicy更改为Always并使用另一个线程中提供的解决方案捕获MessageHandler中的错误详细信息,记录它们,并从发送到客户端的响应中手动擦除它们,但这将是一个讨厌的黑客。)
思考? :/
答案 0 :(得分:1)
我们向微软合作伙伴网络提出了支持请求,他们回复了我认为更好的答案。
我们的想法是将平台的默认IHttpControllerActivator实现替换为包含默认控制器创建行为以及任何其他所需行为的实现。
在我们的例子中,这意味着使用try / catch / throw构造和对我们的日志记录服务的调用来包装DefaultHttpControllerActivator的Create方法。这可能不会给出100%的覆盖率,但是我们所缺少的大部分例外都涉及到控制器的创建,所以它应该有很多帮助。
我真的很想能够在HttpControllerDispatcher中挂钩HandleException方法,但它既是私有的又是静态的,所以meh。
答案 1 :(得分:0)
好的,我明白你要做什么。谢谢你的澄清。 WebAPI有一个模型,其中错误响应不一定是由异常引起的。任何人都可以返回带有400的HttpResponseMessage,例如没有实际抛出异常。在许多情况下,内置框架错误的工作方式相同而不会抛出异常。
现在,我觉得你的建议听起来不错。您可以将ErrorDetailPolicy设置为Always,并实现一个消息处理程序,该消息处理程序记录错误并使用仅包含Message的不同HttpError。这是它的样子:
public class ErrorHandlingMessageHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
HttpError error;
if (response.TryGetContentValue(out error))
{
LogError(error)
// Use an HttpError that doesn't leak internal information
(response.Content as ObjectContent).Value = new HttpError(error.Message);
}
return response;
}
}
请注意,我们没有清除现有错误。我们正在创建一个新的,以减少泄露信息的风险。消息应始终安全地发回。这不包括发回模型状态,但如果需要,您可以随时将其复制到新错误。
考虑这一点的一种方法是,您可以记录您将发送给本地客户端的响应,然后仍然向远程客户端发送不包含错误详细信息的安全消息。