You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web API 2中如何在日志处理器中读取并记录POST请求体?

如何在Web API 2中同时记录HTTP请求头与请求体?

我懂你现在的困扰——用DelegatingHandler记录请求时,只能打印出请求头,POST的JSON请求体完全看不到,甚至调试时在HttpRequestMessage里都找不到它的踪迹。这其实是因为Web API里的请求内容是以流形式存储的,默认不会自动读取,而且流是一次性的,直接调用ToString()根本不会去读取流里的内容。

下面是修改后的完整代码,既能完整记录请求头和请求体,又不会影响后续控制器对请求的正常处理:

enum LogType { Information = 1, Warning = 2, Error = 3 }

public class LogHandler : DelegatingHandler
{
    async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken)
    {
        // 先记录请求头元数据
        Trace.WriteLine(httpRequest.ToString(), LogType.Information.ToString());

        // 检查请求是否包含可读取的内容
        if (httpRequest.Content != null)
        {
            // 异步读取请求体内容
            string requestBody = await httpRequest.Content.ReadAsStringAsync();
            
            // 打印请求体内容
            Trace.WriteLine($"Request Body: {requestBody}", LogType.Information.ToString());

            // 核心操作:读取流后重置内容,避免后续控制器无法读取请求体
            httpRequest.Content = new StringContent(
                requestBody, 
                Encoding.UTF8, 
                httpRequest.Content.Headers.ContentType.MediaType
            );
        }

        // 继续传递请求到后续管道
        var response = await base.SendAsync(httpRequest, cancellationToken);
        return response;
    }
}

关键细节说明:

  • 为什么原来看不到请求体?:HttpRequestMessage.ToString()只会输出请求的元数据(请求方法、URI、头信息),不会主动读取Content里的流内容;调试器也不会自动加载流数据,所以你看不到请求体。
  • 为什么要重新设置Content?:ReadAsStringAsync()会把流的位置移到末尾,如果不重新创建一个StringContent,后续的API控制器尝试读取请求体时会得到空内容。
  • 扩展优化建议:如果你的API需要处理多种Content-Type(比如表单数据、文件上传),可以根据httpRequest.Content.Headers.ContentType做判断,避免读取大文件流导致性能问题。

内容的提问来源于stack exchange,提问作者Swanand Pangam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:07:03