AS.NET WEB API全局异常处理程序无法访问请求内容

时间:2016-06-02 11:00:22

标签: logging asp.net-web-api2

我正在尝试记录有关导致异常的请求的信息。

我试图阅读下面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);
        }
    }

1 个答案:

答案 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);

        }


    }