Registrazione dei messaggi di richiesta / risposta quando si utilizza HttpClient


114

Ho un metodo che esegue un POST come di seguito

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

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

La mia domanda è come posso ottenere il JSON effettivo che è stato pubblicato dall'oggetto entità. Vorrei registrare il JSON che viene POSTATO, quindi sarà bello averlo senza che io debba serializzare un json da solo.

Risposte:


196

Un esempio di come potresti farlo:

Alcune note:

  • LoggingHandlerintercetta la richiesta prima di gestirla alla HttpClientHandlerquale infine scrive sul filo.

  • PostAsJsonAsyncextension crea internamente un ObjectContente quando ReadAsStringAsync()viene chiamato in LoggingHandler, fa sì che il formattatore all'interno ObjectContentserializzi l'oggetto e questo è il motivo per cui stai vedendo il contenuto in json.

Gestore registrazione:

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

Concatena il LoggingHandler sopra con HttpClient :

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

Produzione:

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!"

3
È utile se hai bisogno dei dettagli della richiesta ma non riesce a ottenere la richiesta esatta inviata al server. Se hai bisogno esattamente di tutto il byte inviato al server, non funzionerà in questo modo.
mathk

1
Perché il new HttpClientHandler()? Non è presente nella documentazione ufficiale: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3

1
Ah, a quanto pare è necessario non ottenere un'eccezione sul fatto che il gestore interno sia nullo ...
Zero3

3
Puoi anche sovrascrivere MessageProcessingHandler che sostanzialmente chiama un metodo ProcessRequeste ProcessResponseper te prima e dopo la SendAsyncchiamata.
IllusiveBrian

1
La risposta di @ RamiA di seguito è migliore, perché non richiede modifiche al codice. Una volta terminato il debug, rimuovi la traccia dalla tua configurazione e il gioco è fatto. Non è necessario creare una nuova build.
Tsahi Asher

50

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

Per configurare un listener System.Net per l'output sia nella console che in un file di registro, aggiungere quanto segue al file di configurazione dell'assembly:

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

2
questa è un'ottima soluzione, grazie per aver fatto qualche ricerca e condivisione.
Piwaf

Come funziona ? Ho copiato <system.diagnostics>in app.configsotto <configuration>ma nella bincartella non c'è il file di registro e anche l'output della console non mostra nulla, cosa mi manca?
Muflix

1
@ Muflix, puoi leggere la documentazione che è collegata nella pagina a cui si fa riferimento nella parte superiore della mia risposta. Penso che il nome del file specificato initializeDatanell'attributo verrà creato nella directory di lavoro corrente dell'eseguibile che stai eseguendo, quindi potresti voler controllare quale percorso si trova nel tuo ambiente.
Rami A.

11

Traccia di rete disponibile anche per i prossimi oggetti (vedi articolo su msdn )

  • System.Net.Sockets Alcuni metodi pubblici delle classi Socket, TcpListener, TcpClient e Dns
  • System.Net Alcuni metodi pubblici delle classi HttpWebRequest, HttpWebResponse, FtpWebRequest e FtpWebResponse e informazioni di debug SSL (certificati non validi, elenco degli emittenti mancanti ed errori dei certificati client).
  • System.Net.HttpListener Alcuni metodi pubblici delle classi HttpListener, HttpListenerRequest e HttpListenerResponse.
  • System.Net.Cache Alcuni metodi privati ​​e interni in System.Net.Cache.
  • System.Net.Http Alcuni metodi pubblici delle classi HttpClient, DelegatingHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler e WebRequestHandler.
  • System.Net.WebSockets.WebSocket Alcuni metodi pubblici delle classi ClientWebSocket e WebSocket.

Inserite le successive righe di codice nel file di configurazione

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

-14

La soluzione più semplice sarebbe utilizzare Wireshark e tracciare il flusso tcp HTTP.


9
Immagina un mondo in cui la maggior parte di questi tipi di connessioni sono in realtà HTTPS.
tasto
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.