1

在我们的应用程序中,我们有一组相当简单的日志记录钩子(MVC 和 API 控制器上的 IExceptionFilters 和 Application_Error() 中的一个额外的 catch-all),但是有一整类错误不会触发任何一个。如果从 WebAPI 本身或内部使用的某些东西(例如由依赖解析器创建的类的类型初始化程序)抛出异常,我得到的只是一个 500 响应被发送到客户端。

我发现捕获错误详细信息的唯一方法是使用 HttpConfiguration.IncludeErrorDetailPolicy 来配置应用程序以发出错误详细信息 - 但是,将错误详细信息广播到世界是一种明显的不良做法,所以我宁愿转这完全关闭,或将其设置为有条件的(例如,仅限本地。)..但这意味着远程进入运行应用程序的服务器并使用可以检查响应的工具(如 IE 或 Google)在本地调用 API Chrome),以便弄清楚发生了什么。

我在这里看到了另一个类似的问题(这里),但是提出的解决方案(使用 DelegatingHandler 来检查响应)不能满足我们的需求,我们认为。真的没有我可以挂钩的事件、我可以使用的扩展点或类似的东西来捕获发生的实际异常吗?

(顺便说一句,我想我可以将我的 IncludeErrorDetailPolicy 更改为 Always 并使用另一个线程中提供的解决方案来捕获 MessageHandler 中的错误详细信息,记录它们,并从发送到客户端的响应中手动清除它们,但是将是一个讨厌的黑客。)

想法?:/

4

2 回答 2

1

我们向 Microsoft 合作伙伴网络提出了支持请求,他们返回了我认为更好的答案。

这个想法是用一个将默认控制器创建行为与任何其他所需行为包装起来的实现替换平台的默认 IHttpControllerActivator 实现。

在我们的例子中,这意味着使用 try/catch/throw 结构和对我们的日志服务的调用来包装 DefaultHttpControllerActivator 的 Create 方法。这可能无法提供 100% 的覆盖率,但我们遗漏的大多数例外都与控制器的创建有关,因此它应该会有很大帮助。

我真的很想能够在 HttpControllerDispatcher 中挂钩 HandleException 方法,但它既是私有的又是静态的,所以嗯。

于 2013-02-26T15:57:04.977 回答
0

好的,我明白你想要做什么。感谢您的澄清。WebAPI 有一个模型,错误响应不一定是由异常引起的。例如,任何人都可以返回带有 400 的 HttpResponseMessage,而不会实际抛出异常。在许多情况下,内置框架错误以相同的方式工作而不会引发异常。

现在,我认为你的建议对我来说听起来不错。您可以将 ErrorDetailPolicy 设置为 Always,并实现一个消息处理程序来记录错误并使用仅包含消息的不同 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;
    }
}

请注意,我们没有清除现有错误。我们正在创建一个新的以降低信息泄露的风险。消息应该始终可以安全地发回。这不包括发回模型状态,但如果您需要,您可以随时将其复制到新错误中。

考虑这一点的一种方法是,您可以记录您将发送到本地客户端的响应,然后仍然向远程客户端发送不包含错误详细信息的安全消息。

于 2013-01-18T20:25:41.917 回答