【发布时间】:2019-03-13 17:25:54
【问题描述】:
我正在尝试了解 Web API Http 管道的工作原理!
在我的 Web API 项目中,我使用以下技术来记录/处理异常:
- ExceptionHandler -> 在全局级别处理异常
- ExceptionFilterAttribute -> 处理用户抛出的自定义异常
- DelegatingHandler -> 记录请求和响应数据
每个实现的示例代码:
异常过滤器:
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);
}
}
委托处理程序:
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 中的响应?
解决方案:(2018 年 10 月 9 日更新)
好的,所以我找到了解决方案here
通过修改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有什么区别?
有人能解释一下吗?
【问题讨论】:
标签: c# asp.net-web-api exception-handling