Регистрация сообщений запроса / ответа при использовании HttpClient

115

У меня есть метод, который выполняет POST, как показано ниже

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, который был РАЗМЕЩЕН, так что было бы неплохо иметь это без необходимости выполнять сериализацию json самому.

Говин
источник

Ответы:

198

Пример того, как вы могли бы это сделать:

Некоторые примечания:

  • LoggingHandlerперехватывает запрос до того, как обработает его, HttpClientHandlerкоторый, наконец, записывает в провод.

  • PostAsJsonAsyncextension внутренне создает, 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
Это хорошо, если вам нужны детали запроса, но он не может получить точный запрос, отправленный на сервер. Если вам нужен точно весь байт, отправленный на сервер, это не сработает.
mathk
1
Почему new HttpClientHandler()? Его нет в официальных документах: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Zero3
1
Ах, очевидно, требуется, чтобы не
возникало
3
Вы также можете переопределить MessageProcessingHandler , которые в основном называют ProcessRequestи ProcessResponseметод для вас до и после SendAsyncвызова.
Призрачный Брайан
1
Ответ @ RamiA ниже лучше, потому что он не требует изменения кода. Закончив отладку, вы удаляете трассировку из своей конфигурации, и все. Не нужно делать новую сборку.
Цахи Ашер
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>  
СТУС
источник
-14

Самым простым решением было бы использовать Wireshark и отслеживать поток HTTP tcp.

user1096164
источник
9
Представьте себе мир, в котором большинство таких подключений на самом деле являются HTTPS.
лад