Journalisation des messages de demande / réponse lors de l'utilisation de HttpClient

115

J'ai une méthode qui fait un POST comme ci-dessous

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

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

Ma question est de savoir comment obtenir le JSON réel qui a été publié à partir de l'objet entité. Je voudrais enregistrer le JSON qui est POSTED, donc ce sera bien d'avoir cela sans que je doive faire un json sérialiser moi-même.

gouv
la source

Réponses:

198

Un exemple de la façon dont vous pourriez faire ceci:

Quelques notes:

  • LoggingHandlerintercepte la requête avant de la traiter, HttpClientHandlerqui écrit finalement sur le fil.

  • PostAsJsonAsyncL'extension crée en interne un ObjectContentet quand ReadAsStringAsync()est appelé dans le LoggingHandler, cela amène le formateur à l'intérieur ObjectContentà sérialiser l'objet et c'est la raison pour laquelle vous voyez le contenu dans json.

Gestionnaire de journalisation:

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

Chaîne le LoggingHandler ci-dessus avec HttpClient :

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

Production:

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
la source
3
C'est bien si vous avez besoin des détails de la demande mais que cela ne parvient pas à obtenir la demande exacte envoyée au serveur. Si vous avez besoin précisément de tous les octets envoyés au serveur, cela ne fonctionnera pas de cette façon.
mathk
1
Pourquoi le new HttpClientHandler()? Il n'est pas présent dans la documentation officielle: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3
1
Ah, il est apparemment nécessaire de ne pas obtenir d'exception au sujet du gestionnaire interne étant nul ...
Zero3
3
Vous pouvez également remplacer MessageProcessingHandler qui appelle essentiellement une méthode ProcessRequestand ProcessResponsepour vous avant et après l' SendAsyncappel.
IllusiveBrian
1
La réponse de @ RamiA ci-dessous est meilleure, car elle ne nécessite pas de changement de code. Une fois le débogage terminé, vous supprimez le traçage de votre configuration, et c'est tout. Pas besoin de faire une nouvelle construction.
Tsahi Asher
50

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

Pour configurer un écouteur System.Net pour générer une sortie vers la console et un fichier journal, ajoutez ce qui suit à votre fichier de configuration d'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>
Rami A.
la source
2
c'est une excellente solution, merci de faire quelques recherches et de partager.
Piwaf
Comment ça marche ? Je copiais <system.diagnostics>en app.configsous <configuration>mais dans le bindossier il n'y a pas de fichier journal et la sortie de la console ne pas afficher quoi que ce soit aussi, qu'est - ce que je manque?
Muflix
1
@Muflix, vous pouvez lire la documentation qui est liée dans la page référencée en haut de ma réponse. Je pense que le nom de fichier spécifié dans l' initializeDataattribut sera créé dans le répertoire de travail actuel de l'exécutable que vous exécutez, vous voudrez peut-être vérifier le chemin qui se trouve dans votre environnement.
Rami A.
11

Suivi de réseau également disponible pour les objets suivants (voir l'article sur msdn )

  • System.Net.Sockets Certaines méthodes publiques des classes Socket, TcpListener, TcpClient et Dns
  • System.Net Certaines méthodes publiques des classes HttpWebRequest, HttpWebResponse, FtpWebRequest et FtpWebResponse, ainsi que les informations de débogage SSL (certificats non valides, liste des émetteurs manquants et erreurs de certificat client).
  • System.Net.HttpListener Certaines méthodes publiques des classes HttpListener, HttpListenerRequest et HttpListenerResponse.
  • System.Net.Cache Certaines méthodes privées et internes dans System.Net.Cache.
  • System.Net.Http Certaines méthodes publiques des classes HttpClient, DelegatingHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler et WebRequestHandler.
  • System.Net.WebSockets.WebSocket Certaines méthodes publiques des classes ClientWebSocket et WebSocket.

Mettez les lignes de code suivantes dans le fichier de configuration

<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>  
ÉtuS
la source
-14

La solution la plus simple serait d'utiliser Wireshark et de tracer le flux HTTP tcp.

user1096164
la source
9
Imaginez un monde où la plupart de ces types de connexions sont en fait HTTPS.
frette du