Registro de mensagens de solicitação / resposta ao usar HttpClient

114

Eu tenho um método que faz um POST como abaixo

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

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

Minha pergunta é como posso obter o JSON real que foi postado do objeto de entidade. Eu gostaria de registrar o JSON que é POSTADO, então será bom ter isso sem que eu tenha que fazer uma serialização json sozinho.

govin
fonte

Respostas:

196

Um exemplo de como você pode fazer isso:

Algumas notas:

  • LoggingHandlerintercepta a solicitação antes de tratá-la, o HttpClientHandlerque finalmente grava na transmissão.

  • PostAsJsonAsyncA extensão cria internamente um ObjectContente quando ReadAsStringAsync()é chamada em LoggingHandler, faz com que o formatador interno ObjectContentserialize o objeto e é por essa razão que você está vendo o conteúdo em json.

Manipulador de registro:

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;
    }
}

Encadeie o LoggingHandler acima com HttpClient :

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

Resultado:

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!"
Kiran Challa
fonte
3
Isso é bom se você precisa dos detalhes da solicitação, mas falha em obter a solicitação exata enviada ao servidor. Se precisar exatamente de todo o byte enviado para o servidor não vai funcionar dessa forma.
mathk de
1
Por que new HttpClientHandler()? Não está presente nos documentos oficiais: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3
1
Ah, aparentemente é necessário não obter uma exceção sobre o manipulador interno ser nulo ...
Zero3
3
Você também pode substituir MessageProcessingHandler, que basicamente chama um método ProcessRequeste ProcessResponsepara você antes e depois da SendAsyncchamada.
IllusiveBrian
1
A resposta de @RamiA abaixo é melhor, porque não requer alterações de código. Depois de terminar a depuração, você remove o rastreamento de sua configuração e é isso. Não há necessidade de fazer uma nova construção.
Tsahi Asher de
50

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

Para configurar um ouvinte System.Net para saída para o console e um arquivo de log, adicione o seguinte ao seu arquivo de configuração de montagem:

<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>
Rami A.
fonte
2
esta é uma ótima solução, obrigado por fazer alguma pesquisa e compartilhar.
Piwaf de
Como funciona ? Copiei <system.diagnostics>para app.configem, <configuration>mas na binpasta não há arquivo de log e a saída do console também não exibe nada, o que estou perdendo?
Muflix de
1
@Muflix, você pode ler a documentação que está vinculada na página referenciada no topo da minha resposta. Acho que o nome do arquivo especificado no initializeDataatributo será criado no diretório de trabalho atual do executável que você está executando, portanto, convém verificar qual caminho está em seu ambiente.
Rami A.
11

Rastreamento de rede também disponível para próximos objetos (consulte o artigo no msdn )

  • System.Net.Sockets Alguns métodos públicos das classes Socket, TcpListener, TcpClient e Dns
  • System.Net Alguns métodos públicos das classes HttpWebRequest, HttpWebResponse, FtpWebRequest e FtpWebResponse e informações de depuração SSL (certificados inválidos, lista de emissores ausentes e erros de certificado de cliente).
  • System.Net.HttpListener Alguns métodos públicos das classes HttpListener, HttpListenerRequest e HttpListenerResponse.
  • System.Net.Cache Alguns métodos privados e internos em System.Net.Cache.
  • System.Net.Http Alguns métodos públicos das classes HttpClient, DelegatingHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler e WebRequestHandler.
  • System.Net.WebSockets.WebSocket Alguns métodos públicos das classes ClientWebSocket e WebSocket.

Coloque as próximas linhas de código no arquivo de configuração

<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>  
StuS
fonte
-14

A solução mais fácil seria usar o Wireshark e rastrear o fluxo HTTP tcp.

user1096164
fonte
8
Imagine um mundo onde a maioria desses tipos de conexões sejam na verdade HTTPS.
desgaste de