如何捕获 ASP.NET Web Api中发生的所有未处理的异常,以便我可以记录它们?
到目前为止,我已经尝试过:
ExceptionHandlingAttribute
Application_Error
Global.asax.cs
方法
AppDomain.CurrentDomain.UnhandledException
TaskScheduler.UnobservedTaskException
ExceptionHandlingAttribute
成功处理控制器操作方法和操作过滤器中引发的异常,但不处理其他异常,例如:
IQueryable
无法执行时抛出的异常HttpConfiguration.MessageHandlers
)基本上,如果异常将导致500内部服务器错误返回到客户端,我希望它被记录。实现Application_Error
在Web窗体和MVC中做得很好 - 我可以在Web Api中使用什么?
答案 0 :(得分:153)
现在可以使用WebAPI 2.1(参见What's New):
创建IExceptionLogger的一个或多个实现。例如:
public class TraceExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
Trace.TraceError(context.ExceptionContext.Exception.ToString());
}
}
然后在配置回调中注册您的应用程序的HttpConfiguration,如下所示:
config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
或直接:
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
答案 1 :(得分:19)
Yuval的答案是自定义对Web API捕获的未处理异常的响应,而不是用于记录,如链接page所述。有关详细信息,请参阅页面上的“何时使用”部分。始终调用记录器,但只有在可以发送响应时才调用处理程序。简而言之,使用logger来记录和处理程序来自定义响应。
顺便说一句,我使用的是程序集v5.2.3,而ExceptionHandler
类没有HandleCore
方法。我认为等价物是Handle
。但是,简单地继承ExceptionHandler
(如Yuval的答案中)并不起作用。就我而言,我必须按如下方式实施IExceptionHandler
。
internal class OopsExceptionHandler : IExceptionHandler
{
private readonly IExceptionHandler _innerHandler;
public OopsExceptionHandler (IExceptionHandler innerHandler)
{
if (innerHandler == null)
throw new ArgumentNullException(nameof(innerHandler));
_innerHandler = innerHandler;
}
public IExceptionHandler InnerHandler
{
get { return _innerHandler; }
}
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
Handle(context);
return Task.FromResult<object>(null);
}
public void Handle(ExceptionHandlerContext context)
{
// Create your own custom result here...
// In dev, you might want to null out the result
// to display the YSOD.
// context.Result = null;
context.Result = new InternalServerErrorResult(context.Request);
}
}
请注意,与记录器不同,您可以通过替换默认处理程序来注册处理程序,而不是添加。
config.Services.Replace(typeof(IExceptionHandler),
new OopsExceptionHandler(config.Services.GetExceptionHandler()));
答案 2 :(得分:18)
要回答我自己的问题,这是不可能的!
处理导致内部服务器错误的所有异常似乎是Web API应具备的基本功能,因此我向Microsoft请求了一个 Web API的全局错误处理程序:
https://aspnetwebstack.codeplex.com/workitem/1001
如果您同意,请转到该链接并投票支持!
与此同时,优秀的文章ASP.NET Web API Exception Handling显示了几种不同的方法来捕捉几种不同类型的错误。它比它应该更复杂,并且它不会捕获所有内部服务器错误,但它是目前可用的最佳方法。
更新:全局错误处理现已实施,并可在夜间版本中使用!它将在ASP.NET MVC v5.1中发布。以下是它的工作原理:https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling
答案 3 :(得分:9)
您还可以通过实现IExceptionHandler
接口(或继承ExceptionHandler
基类)来创建全局异常处理程序。在所有已注册的IExceptionLogger
:
IExceptionHandler处理所有未处理的异常 控制器。这是列表中的最后一个。如果发生异常,则 首先调用IExceptionLogger,然后调用控制器 ExceptionFilters,如果仍未处理,则为IExceptionHandler 实施
public class OopsExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong."
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response =
new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
有关here的更多信息。
答案 4 :(得分:0)
我认为我的新global.asax.Application_Error
方法并未在我们的遗留代码中一直调用未处理的异常。
然后我在调用堆栈的中间找到了几个try-catch块,它们在Exception文本上调用了Response.Write。就是这样。将文字倾倒在屏幕上然后杀死了异常石头。