我正在尝试记录有关导致异常的请求的信息。
我试图阅读下面ExceptionHandlerContext附带的请求的内容: -
虽然我可以访问请求对象的其他部分,但其内容始终为空。
在这一点上似乎已经处理好了。
有没有办法在堆栈中捕获请求主体?
public class GlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var exception = context.Exception;
var test = context.Request.Content.ReadAsByteArrayAsync().Result;
var httpException = exception as HttpException;
if (httpException != null)
{
context.Result = new ErrorResult(context.Request, (HttpStatusCode)httpException.GetHttpCode(), httpException.Message);
return;
}
if (exception is BusinessRuleViolationException)
{
context.Result = new ErrorResult(context.Request, HttpStatusCode.PaymentRequired, exception.Message);
return;
}
context.Result = new ErrorResult(context.Request, HttpStatusCode.InternalServerError, exception.Message);
}
}
答案 0 :(得分:3)
对于将来找到此主题的任何人来说,答案很简单,但隐藏得很好。
首先,这里涉及性能问题。
在找到更好的解决方案之前,我会采用以下方法。
这里的问题是Request.Content属性在我们处于管道中的某个点时被处理掉,以便在我们的异常处理程序中记录它。
到目前为止,我找到的唯一解决方法是通过消息处理程序将此属性读入bufferstream。
<强> WARNINING! - 我们将请求的主体提交给记忆。
public class RequestBufferMessageHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
await request.Content.LoadIntoBufferAsync();
return await base.SendAsync(request, cancellationToken);
}
}
注意:您可以使用要传输的内容的最大大小来重载此方法,因此如果请求中存在大文件,则不会尝试将其提交到内存。
我们需要将此注册为HttpConfiguration的消息处理程序,如下所示: -
config.MessageHandlers.Add(new RequestBufferMessageHandler());
现在,当我尝试在我的ExceptionLogger实现中访问它时,我能够访问请求体: -
public class CustomExceptionLogger : ExceptionLogger
{
private readonly ILog _log;
public CustomExceptionLogger(ILogManager logManager)
{
_log = logManager.GetLog(typeof(CustomExceptionLogger));
}
public override async Task LogAsync(ExceptionLoggerContext context, CancellationToken cancellationToken)
{
var body = await context.Request.Content.ReadAsStringAsync();
var data = new
{
requestUrl = context.Request.RequestUri,
requestQueryString = context.RequestContext.RouteData.Values,
requestMethod = context.Request.Method,
requestBody = body,
exception = context.Exception.Message
};
_log.Error(data);
}
}