Search code examples
c#console-applicationdotnet-httpclientsystem.diagnostics.net-4.6.1

How to log outgoing HttpClient request?


I want to connect to REST Api, but it keeps returning status code 400 (Bad Request) no matter how I build the request.

HttpResponseMessage response = client.PostAsync(url, content).Result;

response.EnsureSuccessStatusCode();

My question is, how can I debug my https request to the server ? I would like to see, how my HTTP Request looks like.

I tried to use DiagnosticSource class, so I created Observer classes and subscribe all listeners to it.

Observer

class Observer : IObserver<DiagnosticListener>
    {
        public void OnCompleted()
        {
            throw new NotImplementedException();
        }

        public void OnError(Exception error)
        {
            throw new NotImplementedException();
        }

        public void OnNext(DiagnosticListener value)
        {
            if (value.Name == "HttpHandlerDiagnosticListener")
            {
                value.Subscribe(new HttpClientObserver());
            }
        }
    }

HttpClientObserver

 class HttpClientObserver : IObserver<KeyValuePair<string, object>>
        {
            public void OnCompleted()
            {
                throw new NotImplementedException();
            }
    
            public void OnError(Exception error)
            {
                throw new NotImplementedException();
            }
    
            public void OnNext(KeyValuePair<string, object> value)
            {
                throw new NotImplementedException();
            }
        }

Main

static void Main(string[] args)
        {
            DiagnosticListener.AllListeners.Subscribe(new Diagnostic.Observer());

            // execute HttpClient methods do not throw any event to Observer

But no event was catched. What am I missing, does HttpClient support's DiagnosticSource (How can I recognize which classes do ?). What other solution I can use ?


Solution

  • One of the best solutions is you use the HttpClientToCurl extension in your codes for a better understanding of what send request exactly. This extension will help you to see whatever is set in HttpClient in the form of a curl script.

    You have 3 ways to see script results:

    1- Show in the console:

    httpClient.GenerateCurlInConsole(httpRequestMessage, null);
    

    2- Write in a file:

    httpClient.GenerateCurlInFile(httpRequestMessage, null);
    

    3- Put into a variable:

    string script = httpClient.GenerateCurlInString(httpRequestMessage, null);
    

    Also, the HttpClientToCurl extension has attractive configs that you can see examples in GitHub Address. Moreover, you see the source of the project and see more examples.

    This is a complete example when you want to send a request:

    string requestBody = @"{""name"":""sara"",""requestId"":""10001001"",""amount"":20000}";
    string requestUri = "api/test";
    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
    httpRequestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
    httpRequestMessage.Headers.Add("Authorization", $"Bearer {Guid.NewGuid().ToString()}");
    
    using var httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri("http://localhost:1213/v1/");
    
    httpClient.GenerateCurlInConsole(
        httpRequestMessage,
        config =>
        {
            config.TurnOn = true;
            config.NeedAddDefaultHeaders = true;
            config.EnableCodeBeautification = false;
        });
    
     // Call PostAsync => await client.PostAsync(requestUri, httpRequest.Content);
    

    The extension result is:

    curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"