Я пытаюсь понять, как работает Http-конвейер Web API!
В своем проекте Web API я использую следующую технику для регистрации / обработки исключений:
- ExceptionHandler -> Обработка исключений на глобальном уровне
- ExceptionFilterAttribute -> Обработка пользовательских исключений, выданных пользователем
- DelegatingHandler -> данные журнала запросов и ответов
Пример кода для каждой реализации:
ExceptionFilter:
public class CustomExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var request = context.ActionContext.Request;
if (context.Exception is ItemNotFoundException)
{
context.Response = request.CreateResponse(HttpStatusCode.NotFound, context.Exception.Message);
}
else if (context.Exception is InvalidRequestException)
{
context.Response = request.CreateResponse(HttpStatusCode.BadRequest, context.Exception.Message);
}
}
}
Обработчик исключений:
public class GlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var result = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(Constant.ErrorMessage.InternalServerError)
};
context.Result = new ErrorMessageResult(context.Request, result);
}
}
public class ErrorMessageResult : IHttpActionResult
{
private readonly HttpRequestMessage _request;
private readonly HttpResponseMessage _httpResponseMessage;
public ErrorMessageResult(HttpRequestMessage request, HttpResponseMessage httpResponseMessage)
{
_request = request;
_httpResponseMessage = httpResponseMessage;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_httpResponseMessage);
}
}
DelegatingHandler:
public class LogRequestAndResponseHandler : DelegatingHandler
{
private readonly ILoggingService _loggingService;
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string requestBody = await request.Content.ReadAsStringAsync();
_loggingService.FirstLevelServiceLog(requestBody);
var result = await base.SendAsync(request, cancellationToken);
if (result.Content != null)
{
var responseBody = await result.Content.ReadAsStringAsync();
_loggingService.FirstLevelServiceLog(responseBody);
}
return result;
}
}
Наблюдение:
- Когда есть пользовательское исключение
CustomExceptionFilter
, и позже ответ регистрируется в LogRequestAndResponseHandler
. - Однако, если исключение не обрабатывается, оно входит в
GlobalExceptionHandler
тогда ответ НЕ приходит на LogRequestAndResponseHandler
для регистрации.
Может кто-нибудь дать мне знать, какое изменение кода необходимо сделать в CustomExceptionFilter/GlobalExceptionHandler
, чтобы получить ответв DelegatingHandler
?
Решение: (Обновлено 10/09/2018)
Хорошо, поэтому я нашел решение здесь
Путем изменения кода ExceptionHandler
, я могу поймать ответ в DelegatingHandler
Ключ должен был наследовать от IExceptionHandler
вместо ExceptionHandler
Код:
public class GlobalExceptionHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var httpResponse = context.Request.CreateResponse(HttpStatusCode.InternalServerError, Constant.ErrorMessage.InternalServerError);
context.Result = new ResponseMessageResult(httpResponse);
return Task.FromResult(0);
}
}
Вопрос:
- Я все еще не могу понять, как это работает?В чем разница между
IExceptionHandler
& ExceptionHandler
?
Может ли кто-нибудь пролить свет на это?