Подтвердить что ты не робот

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 (веб-сайтах), хотя встроенный обработчик ошибок отличается.

Любая идея, как это исправить?

4b9b3361

Ответ 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;
}