使用 HttpClient 时记录请求/响应消息

我有一个方法,它可以像下面这样做一个 POST

var response = await client.PostAsJsonAsync(url, entity);


if (response.IsSuccessStatusCode)
{
// read the response as strongly typed object
return await response.Content.ReadAsAsync<T>();
}

我的问题是如何获得从实体对象发布的实际 JSON。我希望记录发布的 JSON,因此,如果不需要我自己进行 JSON 序列化就可以做到这一点。

156822 次浏览

举个例子:

一些注意事项:

  • LoggingHandler在将请求处理到最终写入连接的 HttpClientHandler之前拦截该请求。

  • PostAsJsonAsync扩展在内部创建一个 ObjectContent,当在 LoggingHandler中调用 ReadAsStringAsync()时,它会导致格式化程序 在 ObjectContent中序列化对象,这就是您在 json 中看到内容的原因。

日志处理程序:

public class LoggingHandler : DelegatingHandler
{
public LoggingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}


protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Console.WriteLine("Request:");
Console.WriteLine(request.ToString());
if (request.Content != null)
{
Console.WriteLine(await request.Content.ReadAsStringAsync());
}
Console.WriteLine();


HttpResponseMessage response = await base.SendAsync(request, cancellationToken);


Console.WriteLine("Response:");
Console.WriteLine(response.ToString());
if (response.Content != null)
{
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Console.WriteLine();


return response;
}
}

用 HttpClient 链接上面的 LoggingHandler:

HttpClient client = new HttpClient(new LoggingHandler(new HttpClientHandler()));
HttpResponseMessage response = client.PostAsJsonAsync(baseAddress + "/api/values", "Hello, World!").Result;

产出:

Request:
Method: POST, RequestUri: 'http://kirandesktop:9095/api/values', Version: 1.1, Content: System.Net.Http.ObjectContent`1[
[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Headers:
{
Content-Type: application/json; charset=utf-8
}
"Hello, World!"


Response:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Date: Fri, 20 Sep 2013 20:21:26 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 15
Content-Type: application/json; charset=utf-8
}
"Hello, World!"

最简单的解决方案是使用 金线鲨并跟踪 HTTP tcp 流。

注意: 这适用于.NET Framework,而不适用于.NET Core 或.NET 5 + 。

参见 http://mikehadlow.blogspot.com/2012/07/tracing-systemnet-to-debug-http-clients.html

配置系统。Net 侦听器输出到控制台和日志文件,请将以下内容添加到程序集配置文件:

<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net">
<listeners>
<add name="MyTraceFile"/>
<add name="MyConsole"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="MyTraceFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log" />
<add name="MyConsole" type="System.Diagnostics.ConsoleTraceListener" />
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
</switches>
</system.diagnostics>

网络跟踪也可用于下一个对象(参见关于 我不知道的文章)

  • 系统。网络。插座 Socket、 TcpListener、 TcpClient 和 Dns 类的一些公共方法
  • 系统 HttpWebRequest、 HttpWebResponse、 FtpWebRequest 和 FtpWebResponse 类的一些公共方法以及 SSL 调试信息(无效证书、丢失的发行者列表和客户端证书错误)
  • System.Net.HttpListener HttpListener、 HttpListenerRequest 和 HttpListenerResponse 类的一些公共方法。
  • 系统。网络。缓存 System.Net.Cache 中的一些私有和内部方法。
  • 系统 HttpClient、 RegiatingHandler、 HttpClientHandler、 HttpMessageHandler、 MessageProcessingHandler 和 WebRequestHandler 类的一些公共方法。
  • 系统 ClientWebSocket 和 WebSocket 类的一些公共方法。

将下列代码行放入配置文件:

<configuration>
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Http">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.WebSockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
<add name="System.Net.Http" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
<add name="System.Net.WebSockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
</configuration>