Following the discussion from the official documentation on implementing an IExceptionLogger
(http://www.asp.net/web-api/overview/testing-and-debugging/web-api-glob
Revisiting this topic, I finally have a better understanding of the relationship between IExceptionLogger
, ExceptionFilterAttribute
, and IExceptionHandler
.
From a different source of documentation from the question:
We provide two new user-replaceable services, IExceptionLogger and IExceptionHandler, to log and handle unhandled exceptions. The services are very similar, with two main differences: We support registering multiple exception loggers but only a single exception handler. Exception loggers always get called, even if we’re about to abort the connection. Exception handlers only get called when we’re still able to choose which response message to send. Both services provide access to an exception context containing relevant information from the point where the exception was detected, particularly the HttpRequestMessage, the HttpRequestContext, the thrown exception and the exception source (details below).
And the actual answer to the question:
Exception loggers are the solution to seeing all unhandled exception caught by Web API. Exception handlers are the solution for customizing all possible responses to unhandled exceptions caught by Web API. Exception filters are the easiest solution for processing the subset unhandled exceptions related to a specific action or controller.
And the relevant block of code that illustrates the relationship between the various classes/interfaces (decompiled from ExceptionFilterResult
):
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
ExceptionDispatchInfo exceptionInfo;
try
{
return await this._innerResult.ExecuteAsync(cancellationToken);
}
catch (Exception ex)
{
exceptionInfo = ExceptionDispatchInfo.Capture(ex);
}
Exception exception = exceptionInfo.SourceException;
bool isCancellationException = exception is OperationCanceledException;
ExceptionContext exceptionContext = new ExceptionContext(exception, ExceptionCatchBlocks.IExceptionFilter, this._context);
if (!isCancellationException)
await this._exceptionLogger.LogAsync(exceptionContext, cancellationToken);
HttpActionExecutedContext executedContext = new HttpActionExecutedContext(this._context, exception);
for (int i = this._filters.Length - 1; i >= 0; --i)
{
IExceptionFilter exceptionFilter = this._filters[i];
await exceptionFilter.ExecuteExceptionFilterAsync(executedContext, cancellationToken);
}
if (executedContext.Response == null && !isCancellationException)
executedContext.Response = await this._exceptionHandler.HandleAsync(exceptionContext, cancellationToken);
if (executedContext.Response != null)
return executedContext.Response;
if (exception == executedContext.Exception)
exceptionInfo.Throw();
throw executedContext.Exception;
}