การบันทึกข้อความร้องขอ / ตอบกลับเมื่อใช้ HttpClient


115

ฉันมีวิธีการโพสต์ดังต่อไปนี้

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 ที่ได้รับ POSTED ดังนั้นจะเป็นการดีที่จะมีโดยที่ฉันไม่ต้องทำ json ให้เป็นอนุกรมด้วยตัวเอง

คำตอบ:


198

ตัวอย่างวิธีที่คุณสามารถทำได้:

หมายเหตุบางประการ:

  • LoggingHandlerสกัดกั้นคำขอก่อนที่จะจัดการHttpClientHandlerซึ่งในที่สุดก็เขียนไปที่สายไฟ

  • PostAsJsonAsyncส่วนขยายจะสร้างภายในObjectContentและเมื่อReadAsStringAsync()ถูกเรียกในสิ่งLoggingHandlerนี้จะทำให้ฟอร์แมตเตอร์ภายใน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;
    }
}

เชื่อมต่อ LoggingHandler ข้างต้นกับ HttpClient :

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

3
เป็นเรื่องดีถ้าคุณต้องการรายละเอียดคำขอ แต่ล้มเหลวในการรับคำขอที่ถูกต้องที่ส่งไปยังเซิร์ฟเวอร์ หากคุณต้องการไบต์ทั้งหมดที่ส่งไปยังเซิร์ฟเวอร์อย่างแม่นยำมันจะไม่ทำงานในลักษณะนี้
คณิตศาสตร์

1
ทำไมnew HttpClientHandler()? ไม่มีอยู่ในเอกสารอย่างเป็นทางการ: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3

1
อาเห็นได้ชัดว่าจำเป็นต้องไม่มีข้อยกเว้นเกี่ยวกับตัวจัดการด้านในเป็นโมฆะ ...
Zero3

3
คุณยังสามารถแทนที่MessageProcessingHandlerซึ่งโดยทั่วไปจะเรียกใช้ a ProcessRequestและProcessResponseวิธีการสำหรับคุณก่อนและหลังการSendAsyncโทร
IllusiveBrian

1
คำตอบของ @ RamiA ด้านล่างดีกว่าเพราะไม่ต้องเปลี่ยนรหัส เมื่อคุณแก้ไขจุดบกพร่องเสร็จแล้วคุณจะลบการติดตามออกจากการกำหนดค่าของคุณเท่านี้ก็เสร็จเรียบร้อย ไม่ต้องสร้างใหม่
Tsahi Asher

50

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

ในการกำหนดค่าตัวฟัง System.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>

2
นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยมขอขอบคุณสำหรับการค้นคว้าและแบ่งปัน
Piwaf

มันทำงานอย่างไร? ฉันคัดลอก<system.diagnostics>ไว้ข้างapp.configใต้<configuration>แต่ในbinโฟลเดอร์ไม่มีไฟล์บันทึกและเอาต์พุตคอนโซลไม่แสดงอะไรเลยฉันขาดอะไรไป?
Muflix

1
@Muflix คุณสามารถอ่านเอกสารที่เชื่อมโยงในหน้าที่อ้างถึงที่ด้านบนของคำตอบของฉัน ฉันคิดว่าชื่อไฟล์ที่ระบุในinitializeDataแอตทริบิวต์จะถูกสร้างขึ้นในไดเร็กทอรีการทำงานปัจจุบันของไฟล์ปฏิบัติการที่คุณกำลังเรียกใช้ดังนั้นคุณอาจต้องการตรวจสอบว่าเส้นทางใดที่อยู่ในสภาพแวดล้อมของคุณ
รามีอ.

11

นอกจากนี้ยังมีการติดตามเครือข่ายสำหรับวัตถุถัดไป (ดูบทความเกี่ยวกับ msdn )

  • System.Net.Sockets วิธีการสาธารณะบางอย่างของคลาส Socket, TcpListener, TcpClient และ Dns
  • System.Net วิธีการสาธารณะบางอย่างของ HttpWebRequest, HttpWebResponse, FtpWebRequest และคลาส FtpWebResponse และข้อมูลการดีบัก SSL (ใบรับรองไม่ถูกต้องรายการผู้ออกที่หายไปและข้อผิดพลาดใบรับรองไคลเอ็นต์)
  • System.Net.HttpListener วิธีการสาธารณะบางอย่างของคลาส HttpListener, HttpListenerRequest และ HttpListenerResponse
  • System.Net.Cache วิธีการส่วนตัวและภายในบางวิธีใน System.Net.Cache
  • System.Net.Http วิธีการสาธารณะบางอย่างของ HttpClient, DelegatingHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler และ WebRequestHandler
  • System.Net.WebSockets.WebSocket วิธีการสาธารณะบางอย่างของคลาส 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>  

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.