WebApi v2 ExceptionHandler не вызван
Как получается, что пользовательский ExceptionHandler
никогда не вызывается, и вместо этого возвращается стандартный ответ (а не тот, который я хочу)?
Зарегистрировано как это
config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
и реализован следующим образом
public class GlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
context.Result = new ExceptionResponse
{
statusCode = context.Exception is SecurityException ? HttpStatusCode.Unauthorized : HttpStatusCode.InternalServerError,
message = "An internal exception occurred. We'll take care of it.",
request = context.Request
};
}
}
public class ExceptionResponse : IHttpActionResult
{
public HttpStatusCode statusCode { get; set; }
public string message { get; set; }
public HttpRequestMessage request { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(statusCode);
response.RequestMessage = request;
response.Content = new StringContent(message);
return Task.FromResult(response);
}
}
и выбрасывается таким образом (тест)
throw new NullReferenceException("testerror");
в контроллере или в репозитории.
UPDATE
У меня нет другого ExceptionFilter
.
Я нашел триггер для этого поведения:
Указанный URL
GET http://localhost:XXXXX/template/lock/someId
отправка этого заголовка, мой ExceptionHandler
работает
Host: localhost:XXXXX
отправка этого заголовка, он не работает, и встроенный обработчик вместо этого возвращает ошибку
Host: localhost:XXXXX
Origin: http://localhost:YYYY
Это может быть проблема с запросами CORS (я использую пакет WebPAP CORS по всему миру с помощью подстановочных знаков) или, в конечном счете, мой регистратор ELMAH. Это также происходит при размещении на Azure (веб-сайтах), хотя встроенный обработчик ошибок отличается.
Любая идея, как это исправить?
Ответы
Ответ 1
Выключает по умолчанию, обрабатывает только внешние исключения, а не исключения в классах репозитория. Поэтому ниже должно быть переопределено:
public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
return context.ExceptionContext.IsOutermostCatchBlock;
}
ОБНОВЛЕНИЕ 1
WebAPI v2 больше не использует IsOutermostCatchBlock
. Во всяком случае, ничего не меняется в моей реализации, так как новый код в ShouldHandle
все еще предотвращает мой обработчик ошибок. Поэтому я использую это, и мой обработчик ошибок однажды вызван. Я ломаю ошибки в контроллерах и репозиториях таким образом.
public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
return true;
}
ОБНОВЛЕНИЕ 2
Поскольку в этом вопросе было так много внимания, обратите внимание, что текущее решение - это связанное от @JustAMartin в комментариях ниже.
Ответ 2
Настоящим виновником является CorsMessageHandler, вставленный методом EnableCors в конвейер обработки сообщений. Блок catch перехватывает любое исключение и преобразовывает в ответ, прежде чем он сможет достичь блока try-catch HTTPServer, и может быть вызвана логика ExceptionHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
CorsRequestContext corsRequestContext = request.GetCorsRequestContext();
HttpResponseMessage result;
if (corsRequestContext != null)
{
try
{
if (corsRequestContext.IsPreflight)
{
result = await this.HandleCorsPreflightRequestAsync(request, corsRequestContext, cancellationToken);
return result;
}
result = await this.HandleCorsRequestAsync(request, corsRequestContext, cancellationToken);
return result;
}
catch (Exception exception)
{
result = CorsMessageHandler.HandleException(request, exception);
return result;
}
}
result = await this.<>n__FabricatedMethod3(request, cancellationToken);
return result;
}