Ghi nhật ký thông báo yêu cầu / phản hồi khi sử dụng HttpClient


114

Tôi có một phương thức thực hiện một BÀI ĐĂNG như bên dưới

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

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

Câu hỏi của tôi là làm cách nào để có được JSON thực tế đã được đăng từ đối tượng entity. Tôi muốn ghi nhật ký JSON được POSTED, vì vậy sẽ rất tuyệt nếu có điều đó mà tôi không cần phải tự tuần tự hóa json.

Câu trả lời:


196

Một ví dụ về cách bạn có thể làm điều này:

Một số lưu ý:

  • LoggingHandlerchặn yêu cầu trước khi nó xử lý yêu cầu HttpClientHandlermà cuối cùng sẽ ghi vào dây.

  • PostAsJsonAsynctiện ích mở rộng nội bộ tạo ra một ObjectContentvà khi nào ReadAsStringAsync()được gọi trong LoggingHandler, nó làm cho trình định dạng bên trong ObjectContenttuần tự hóa đối tượng và đó là lý do bạn thấy nội dung trong json.

Trình xử lý ghi nhật ký:

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

Chuỗi LoggingHandler ở trên với HttpClient :

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

Đầu ra:

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
Điều đó thật tuyệt nếu bạn cần chi tiết yêu cầu nhưng không thể nhận được yêu cầu chính xác được gửi đến máy chủ. Nếu bạn cần chính xác tất cả byte được gửi đến máy chủ, nó sẽ không hoạt động theo cách này.
mathk

1
Tại sao new HttpClientHandler()? Nó không có trong tài liệu chính thức: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3

1
Ah, nó được rõ ràng cần thiết để không nhận được một ngoại lệ về null xử lý bên trong là ...
Zero3

3
Bạn cũng có thể ghi đè MessageProcessingHandler về cơ bản gọi a ProcessRequestProcessResponsephương thức cho bạn trước và sau SendAsynccuộc gọi.
Ảo giácBrian

1
Câu trả lời của @ RamiA dưới đây tốt hơn, vì nó không yêu cầu thay đổi mã. Khi bạn gỡ lỗi xong, bạn xóa dấu vết khỏi cấu hình của mình, và thế là xong. Không cần phải tạo một bản dựng mới.
Tsahi Asher 20/02/18

50

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

Để định cấu hình trình nghe System.Net để xuất ra cả bảng điều khiển và tệp nhật ký, hãy thêm phần sau vào tệp cấu hình lắp ráp của bạn:

<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
đây là một giải pháp tuyệt vời, cảm ơn bạn đã thực hiện một số nghiên cứu và chia sẻ.
Piwaf

Làm thế nào nó hoạt động ? Tôi đã sao chép <system.diagnostics>vào app.configdưới <configuration>nhưng trong binthư mục không có tệp nhật ký và đầu ra bảng điều khiển cũng không hiển thị bất kỳ thứ gì, tôi đang thiếu cái gì?
Muflix

1
@Muflix, bạn có thể đọc tài liệu được liên kết trong trang được tham chiếu ở đầu câu trả lời của tôi. Tôi nghĩ rằng tên tệp được chỉ định trong initializeDatathuộc tính sẽ được tạo trong thư mục làm việc hiện tại của tệp thực thi mà bạn đang chạy, vì vậy bạn có thể muốn kiểm tra đường dẫn nào trong môi trường của mình.
Rami A.

11

Theo dõi mạng cũng có sẵn cho các đối tượng tiếp theo (xem bài viết trên msdn )

  • System.Net.Sockets Một số phương thức công khai của các lớp Socket, TcpListener, TcpClient và Dns
  • System.Net Một số phương thức công khai của các lớp HttpWebRequest, HttpWebResponse, FtpWebRequest và FtpWebResponse và thông tin gỡ lỗi SSL (chứng chỉ không hợp lệ, danh sách tổ chức phát hành bị thiếu và lỗi chứng chỉ ứng dụng khách.)
  • System.Net.HttpListener Một số phương thức công khai của các lớp HttpListener, HttpListenerRequest và HttpListenerResponse.
  • System.Net.Cache Một số phương thức riêng và nội bộ trong System.Net.Cache.
  • System.Net.Http Một số phương thức công khai của các lớp HttpClient, DelegateHandler, HttpClientHandler, HttpMessageHandler, MessageProcessingHandler và WebRequestHandler.
  • System.Net.WebSockets.WebSocket Một số phương thức công khai của các lớp ClientWebSocket và WebSocket.

Đặt các dòng mã tiếp theo vào tệp cấu hình

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.