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
相关产品推荐
相关产品推荐

