ASP.NET Web Api 2.0 中的 ExceptionFilter 或 ExceptionHandler 哪个优先?
Which one takes priority, ExceptionFilter or ExceptionHandler in ASP.NET Web Api 2.0?
我的网络 api 2.0 中有一个全局异常处理程序,它处理所有未处理的异常,以便 return 向 api 调用者发送友好的错误消息。
我还有一个全局 ExceptionFilter,它处理我的网络中非常具体的异常 api 和 returns 一个特定的响应。 ExceptionFilter 由插件动态添加到我的网站 api 所以我无法在我的 ExceptionHandler 中执行它的操作。
我想知道如果我在全局注册了ExceptionHandler和ExceptionFilter,哪个会优先执行?现在我可以看到 ExceptionFilter 在 ExceptionHandler 之前被执行。而且我还可以在我的 ExceptionFilter 中看到,如果我创建响应,ExceptionHandler 不会被执行。
假设安全吗:
ExceptionFilters 在 ExceptionHandlers 之前执行。
如果 ExceptionFilter 创建了一个响应,ExceptionHandler 将不会被执行。
我必须调试 System.Web.Http 才能找到问题的答案。所以答案是:
可以安全地假设 ExceptionFilters 将在 ExceptionHandlers 之前执行
如果 ExceptionFilter 创建了一个响应,ExceptionHandler 将不会被执行。
为什么会这样:
当您注册了一个 ExceptionFilter 以全局执行或为您的控制器操作执行时,所有 api 控制器继承的 ApiController 基础 class 会将结果包装在 ExceptionFilterResult 中并调用其 ExecuteAsync方法。这是 ApiController 中的代码,它执行以下操作:
if (exceptionFilters.Length > 0)
{
IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices);
IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
result);
}
return result.ExecuteAsync(cancellationToken);
查看 ExceptionFilterResult.ExecuteAsync 方法:
try
{
return await _innerResult.ExecuteAsync(cancellationToken);
}
catch (Exception e)
{
exceptionInfo = ExceptionDispatchInfo.Capture(e);
}
// This code path only runs if the task is faulted with an exception
Exception exception = exceptionInfo.SourceException;
Debug.Assert(exception != null);
bool isCancellationException = exception is OperationCanceledException;
ExceptionContext exceptionContext = new ExceptionContext(
exception,
ExceptionCatchBlocks.IExceptionFilter,
_context);
if (!isCancellationException)
{
// We don't log cancellation exceptions because it doesn't represent an error.
await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);
}
HttpActionExecutedContext executedContext = new HttpActionExecutedContext(_context, exception);
// Note: exception filters need to be scheduled in the reverse order so that
// the more specific filter (e.g. Action) executes before the less specific ones (e.g. Global)
for (int i = _filters.Length - 1; i >= 0; i--)
{
IExceptionFilter exceptionFilter = _filters[i];
await exceptionFilter.ExecuteExceptionFilterAsync(executedContext, cancellationToken);
}
if (executedContext.Response == null && !isCancellationException)
{
// We don't log cancellation exceptions because it doesn't represent an error.
executedContext.Response = await _exceptionHandler.HandleAsync(exceptionContext, cancellationToken);
}
可以看到先执行ExceptionLogger,然后执行所有ExceptionFilters,然后if if executedContext.Response == null,执行ExceptionHandler。
希望有用!
我的网络 api 2.0 中有一个全局异常处理程序,它处理所有未处理的异常,以便 return 向 api 调用者发送友好的错误消息。 我还有一个全局 ExceptionFilter,它处理我的网络中非常具体的异常 api 和 returns 一个特定的响应。 ExceptionFilter 由插件动态添加到我的网站 api 所以我无法在我的 ExceptionHandler 中执行它的操作。
我想知道如果我在全局注册了ExceptionHandler和ExceptionFilter,哪个会优先执行?现在我可以看到 ExceptionFilter 在 ExceptionHandler 之前被执行。而且我还可以在我的 ExceptionFilter 中看到,如果我创建响应,ExceptionHandler 不会被执行。
假设安全吗:
ExceptionFilters 在 ExceptionHandlers 之前执行。
如果 ExceptionFilter 创建了一个响应,ExceptionHandler 将不会被执行。
我必须调试 System.Web.Http 才能找到问题的答案。所以答案是:
可以安全地假设 ExceptionFilters 将在 ExceptionHandlers 之前执行
如果 ExceptionFilter 创建了一个响应,ExceptionHandler 将不会被执行。
为什么会这样:
当您注册了一个 ExceptionFilter 以全局执行或为您的控制器操作执行时,所有 api 控制器继承的 ApiController 基础 class 会将结果包装在 ExceptionFilterResult 中并调用其 ExecuteAsync方法。这是 ApiController 中的代码,它执行以下操作:
if (exceptionFilters.Length > 0)
{
IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices);
IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
result);
}
return result.ExecuteAsync(cancellationToken);
查看 ExceptionFilterResult.ExecuteAsync 方法:
try
{
return await _innerResult.ExecuteAsync(cancellationToken);
}
catch (Exception e)
{
exceptionInfo = ExceptionDispatchInfo.Capture(e);
}
// This code path only runs if the task is faulted with an exception
Exception exception = exceptionInfo.SourceException;
Debug.Assert(exception != null);
bool isCancellationException = exception is OperationCanceledException;
ExceptionContext exceptionContext = new ExceptionContext(
exception,
ExceptionCatchBlocks.IExceptionFilter,
_context);
if (!isCancellationException)
{
// We don't log cancellation exceptions because it doesn't represent an error.
await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);
}
HttpActionExecutedContext executedContext = new HttpActionExecutedContext(_context, exception);
// Note: exception filters need to be scheduled in the reverse order so that
// the more specific filter (e.g. Action) executes before the less specific ones (e.g. Global)
for (int i = _filters.Length - 1; i >= 0; i--)
{
IExceptionFilter exceptionFilter = _filters[i];
await exceptionFilter.ExecuteExceptionFilterAsync(executedContext, cancellationToken);
}
if (executedContext.Response == null && !isCancellationException)
{
// We don't log cancellation exceptions because it doesn't represent an error.
executedContext.Response = await _exceptionHandler.HandleAsync(exceptionContext, cancellationToken);
}
可以看到先执行ExceptionLogger,然后执行所有ExceptionFilters,然后if if executedContext.Response == null,执行ExceptionHandler。
希望有用!