Mencatat permintaan / tanggapan pesan saat menggunakan HttpClient

114

Saya memiliki metode yang melakukan POST seperti di bawah ini

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

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

Pertanyaan saya adalah bagaimana saya bisa mendapatkan JSON sebenarnya yang diposting dari objek entitas. Saya ingin log JSON yang mendapat POSTING, jadi akan menyenangkan untuk memilikinya tanpa saya harus melakukan serialisasi json sendiri.

govin
sumber

Jawaban:

196

Contoh bagaimana Anda bisa melakukan ini:

Beberapa catatan:

  • LoggingHandlermemotong permintaan sebelum menanganinya HttpClientHandleryang akhirnya menulis ke kabel.

  • PostAsJsonAsyncextension secara internal membuat ObjectContentdan ketika ReadAsStringAsync()dipanggil di LoggingHandler, itu menyebabkan pemformat di dalam ObjectContentmembuat serial objek dan itulah alasan Anda melihat konten di json.

Penangan logging:

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

Rangkai LoggingHandler di atas dengan HttpClient :

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

Keluaran:

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
sumber
3
Itu bagus jika Anda memerlukan detail permintaan tetapi gagal mendapatkan permintaan yang tepat dikirim ke server. Jika Anda membutuhkan tepat semua byte yang dikirim ke server itu tidak akan bekerja dengan cara ini.
mathk
1
Mengapa new HttpClientHandler()? Itu tidak ada di dokumen resmi: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3
1
Ah, tampaknya diperlukan untuk tidak mendapatkan pengecualian tentang inner handler yang null ...
Zero3
3
Anda juga dapat mengganti MessageProcessingHandler yang pada dasarnya memanggil metode ProcessRequestdan ProcessResponseuntuk Anda sebelum dan sesudah SendAsyncpanggilan.
IllusiveBrian
1
Jawaban @ RamiA di bawah ini lebih baik, karena tidak memerlukan perubahan kode. Setelah Anda selesai men-debug, Anda menghapus pelacakan dari konfigurasi Anda, dan hanya itu. Tidak perlu membuat bangunan baru.
Tsahi Asher
50

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

Untuk mengonfigurasi pendengar System.Net ke output ke konsol dan file log, tambahkan baris berikut ke file konfigurasi assembly Anda:

<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.
sumber
2
ini adalah solusi yang bagus, terima kasih telah melakukan penelitian dan berbagi.
Piwaf
Bagaimana cara kerjanya ? Saya salin <system.diagnostics>ke app.configbawah <configuration>tetapi di binfolder tidak ada file log dan output konsol tidak menampilkan apa-apa juga, apa yang saya lewatkan?
Muflix
1
@ Muflix, Anda dapat membaca dokumentasi yang ditautkan di halaman yang direferensikan di bagian atas jawaban saya. Saya pikir nama file yang ditentukan dalam initializeDataatribut akan dibuat di direktori kerja saat ini dari executable yang Anda jalankan, jadi Anda mungkin ingin memeriksa jalur mana yang ada di lingkungan Anda.
Rami A.
11

Pelacakan jaringan juga tersedia untuk objek berikutnya (lihat artikel tentang msdn )

  • System.Net.Sockets Beberapa metode umum kelas Socket, TcpListener, TcpClient, dan Dns
  • System.Net Beberapa metode publik dari kelas HttpWebRequest, HttpWebResponse, FtpWebRequest, dan FtpWebResponse, dan informasi debug SSL (sertifikat tidak valid, daftar penerbit hilang, dan kesalahan sertifikat klien.)
  • System.Net.HttpListener Beberapa metode umum kelas HttpListener, HttpListenerRequest, dan HttpListenerResponse.
  • System.Net.Cache Beberapa metode pribadi dan internal di System.Net.Cache.
  • System.Net.Http Beberapa metode umum kelas HttpClient, DelegatingHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler, dan WebRequestHandler.
  • System.Net.WebSockets.WebSocket Beberapa metode publik kelas ClientWebSocket dan WebSocket.

Letakkan baris kode berikutnya ke file konfigurasi

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

Solusi termudah adalah dengan menggunakan Wireshark dan melacak aliran tcp HTTP.

pengguna1096164
sumber
9
Bayangkan sebuah dunia di mana sebagian besar jenis koneksi ini sebenarnya adalah HTTPS.
resah