Link to home
Start Free TrialLog in
Avatar of N M
N MFlag for Luxembourg

asked on

C# HTTPrequest - how to get the whole request and whole response.

I have the below small console program to consume a restAPI.
I have difficulty to see *what exactly* am I sending (the WHOLE request) and *what exactly* am I getting back as a response (the WHOLE response).
I have tried many Console.WriteLines with various arguments, but seems I have not managed to have a concrete results (WHOLE request and WHOLE response).

Could you help me please? The whole code below.

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;


namespace TEST_API
{
    public partial class ConsentHeaders
    {
        [JsonProperty("CL-ID")]
        public string CL_ID { get; set; }

        [JsonProperty("X-ID")]
        public string X_ID { get; set; }

        [JsonProperty("P-Token")]
        public string P_Token { get; set; }
    }

    public partial class access
    {
        [JsonProperty("aP2")]
        public string aP2 { get; set; } = "allAccounts";

        [JsonProperty("aAcc")] 
        public string aAcc { get; set; } = "allAccounts";
    }

    public partial class ConsentBody
    {
        [JsonProperty("access")]
        public access access { get; internal set; }

        [JsonProperty("combinedServiceIndicator")]
        public Boolean combinedServiceIndicator { get; set; } = false;

        [JsonProperty("frequencyPerDay")]
        public int frequencyPerDay { get; set; } = 4;

        [JsonProperty("recurringIndicator")]
        public Boolean recurringIndicator { get; set; } = false;

        [JsonProperty("validUntil")]
        public string validUntil { get; set; } = "2019-12-31";
    }


    class Program
    {
        private static void Main()
        {
            ConsentHeaders cust_consent_headers = new ConsentHeaders
            {
                X_ID = "d587612Xq99",
                CL_ID = "8010aFQ9127",
                P_Token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ",
            };

            ConsentBody cust_consent = new ConsentBody //{ };

            // You may choose to edit/update any value, otherwise defaults will be used.
                
                {
                    access = new access
                    {
                        aP2 = "allAccounts",
                        aAcc = "allAccounts"
                    },
                    combinedServiceIndicator = false,
                    frequencyPerDay = 4,
                    recurringIndicator = false,
                    validUntil = "2019-12-31"
                };
            
            System.Uri URL = new System.Uri("http://MyService:8001/some/api/do/something");

            CreateConsentAsync(URL, cust_consent_headers, cust_consent).GetAwaiter().GetResult();
        }

        static HttpClient client = new HttpClient();

        static async Task CreateConsentAsync(Uri HTTPaddress, ConsentHeaders cconsentHeaders, ConsentBody cconsent)
        {
            try
            {
                client.BaseAddress = HTTPaddress;
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
                client.DefaultRequestHeaders.Add("Connection", "keep-alive");
                client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");

                client.DefaultRequestHeaders.Add("CL-ID", cconsentHeaders.CL_ID);
                client.DefaultRequestHeaders.Add("X-ID", cconsentHeaders.X_ID);
                client.DefaultRequestHeaders.Add("P-Token", cconsentHeaders.P_Token);

                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);

                request.Content = new StringContent(JsonConvert.SerializeObject(cconsent, Formatting.Indented), System.Text.Encoding.UTF8, "application/json");

                    
                await client.SendAsync(request).ContinueWith(responseTask => { Console.WriteLine("Response: {0}", responseTask.Result);});
            }
            catch (Exception e)
            {
                Console.WriteLine("Error in " + e.TargetSite + "\r\n" + e.Message);
            }
            Console.ReadLine();
        }
    }
}

Open in new window

Avatar of N M
N M
Flag of Luxembourg image

ASKER

*Note: if you spot any bug, kindly respond, I'm new on this. Thank you very much.
Avatar of gr8gonzo
You can use tracing to capture the raw request and response. I built a library to make it a very simple process:

https://github.com/jhilgeman/HttpRawTraceListener
On a side note, an even easier way is to install and use Fiddler. That program simply examines HTTP network activity on your computer (across all apps, not just your program). My library I mentioned above is if you need to access the request/response from within code.
Avatar of N M

ASKER

Thank you, I will try it, but seems complicated, I was just looking to have all the request in a string and all the response in a string. I will make an efrort to follow your advice - thank you!
I was just looking to have all the request in a string and all the response in a string.
That's ultimately what my library does.

The bigger question is what your goal is. If it's just to examine and debug, then Fiddler is the simplest approach. You can be up and running in minutes.

If you need it as a string because you want to do something extra with the data, then that is what my library is for. Make sure you look at the example. It's very simple to set up.
Avatar of N M

ASKER

Thank you, I just copied the code inside the same namespace, added System.IO and now thinking how to use it to get the whole request and response.. Thank you
I'm not sure what you mean by copying the code into your namespace. It's intended to be a drop-in file (you cannot remove the copyright or header).

Just save the file as-is into your project and then in your solution explorer, right-click the file and Include it to make it part of your project. Then just use the example usage code. The example shows you how to get the full request and response.
Avatar of N M

ASKER

I will do so (no I didnt remove the copyright, no need to pretend is my code). Just trying to see how to get the full string response.. I will follow your advice here.
Avatar of N M

ASKER

Still trying to have the request, I was wondering if there is any simpler solution; kindly advise.

I have added this namespace, in different file, and all is good.
I am inside my code, in the static async Task CreateConsentAsync and inside the 'try' right after my 'await client.SendAsync' I put the trace listener.
Here is that part:

            try
            {
                client.BaseAddress = HTTPaddress;
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
                client.DefaultRequestHeaders.Add("Connection", "keep-alive");
                client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");

                client.DefaultRequestHeaders.Add("... etc.



                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);

                request.Content = new StringContent(JsonConvert.SerializeObject(cconsent, Formatting.Indented), System.Text.Encoding.UTF8, "application/json");

                Console.WriteLine(client.DefaultRequestHeaders);
                Console.WriteLine(JsonConvert.SerializeObject(cconsent, Formatting.Indented));

                await client.SendAsync(request).ContinueWith(responseTask => { Console.WriteLine("Response: {0}", responseTask.Result); });


                System.Diagnostics.HttpRawTraceListener.Initialize();

                System.Diagnostics.HttpRawTraceListener.FinishedCommunication += System.Diagnostics.HttpRawTraceListener_FinishedCommunication;

                private void HttpRawTraceListener_FinishedCommunication(object sender, System.Diagnostics.CommunicationEventArgs e)
                {
                    Console.WriteLine("Raw Request: " + e.Communication.RequestString);
                    Console.WriteLine("Raw Response: " + e.Communication.ResponseString); 
                }


            }
            catch (Exception e)
            {
                Console.WriteLine("Error in " + e.TargetSite + "\r\n" + e.Message);
            }
            Console.ReadLine();
        }

Open in new window


So, I have error on the "System.Diagnostics.HttpRawTraceListener_FinishedCommunication" that says it does not recognise the namespace ("does not exist in System.Diagnostics namespace, are you missing an assembly or reference?" - but I am not). And in private void HttpRawTraceListener_FinishedCommunication does not accept the "private" (throws error "the modifier 'private' is not valid for this item".

Apologies, couldn't debug so I revert code to previous stage.
You are not putting the code in the right place. These two lines:
System.Diagnostics.HttpRawTraceListener.Initialize();
System.Diagnostics.HttpRawTraceListener.FinishedCommunication += System.Diagnostics.HttpRawTraceListener_FinishedCommunication;

Open in new window

...need to only run once, so put them into your startup code.

The second part is an event handler method so it needs to go outside your current method.

To be honest, I'm concerned that you don't know C# syntax. This is not something you should try to do by cutting and pasting code snippets from the internet. It is more involved than that because of the way that .NET handles tracing. So at minimum you should understand event handlers and static vs. non-static code. Otherwise this won't make sense (and there is no simpler way to get the full request and response in every situation - both successful and failed requests).
Avatar of N M

ASKER

Dear sir,

Indeed I am trying to have a steep learn curve to walk, but I am trying. After all, this is the reason I am asking the help from the experts here.. both solving a problem and learning through this.
I am taking your advice quite seriously, however, still the code didn't compile.. Well, I will keep trying..
You may look my effort and error messages in the comment before yours.
Thank you for the comments, and I appreciate your time.
Avatar of N M

ASKER

So, for the POST indeed this would reveal the Post request:
Console.WriteLine("POST Request: " + "\r\n" + client.DefaultRequestHeaders + "\r\n" + JsonConvert.SerializeObject(cconsent, Formatting.Indented) + "\r\n");

and for the response, instead of using the
responseTask.Result
we can use
responseTask.Result.Content.ReadAsStringAsync().Result


static async Task CreateConsentAsync(Uri HTTPaddress, ConsentHeaders cconsentHeaders, ConsentBody cconsent)
{
	HttpClient client = new HttpClient();

	try
	{
		client.BaseAddress = HTTPaddress;
		client.DefaultRequestHeaders.Accept.Clear();
		client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
		client.DefaultRequestHeaders.Add("Connection", "keep-alive");
		client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
		//add more headears here as per your needs..
		client.DefaultRequestHeaders.Add("my header", yourValue);
		//...

		HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);

		request.Content = new StringContent(JsonConvert.SerializeObject(cconsent, Formatting.Indented), System.Text.Encoding.UTF8, "application/json");

		Console.WriteLine("POST Request: " + "\r\n" + client.DefaultRequestHeaders + "\r\n" + JsonConvert.SerializeObject(cconsent, Formatting.Indented) + "\r\n");

		await client.SendAsync(request).ContinueWith(responseTask => {Console.WriteLine("Response:\r\n{0}", responseTask.Result.Content.ReadAsStringAsync().Result);});

		Console.ReadLine();
	}
	catch (Exception e)
	{
		Console.WriteLine("Error in " + e.TargetSite + "\r\n" + e.Message);
		Console.ReadLine();
	}
}

Open in new window

Avatar of N M

ASKER

Any better (as simple as possible) solutions, to get the whole POST message and the whole Request sent back, are welcome. Thank you.
ASKER CERTIFIED SOLUTION
Avatar of gr8gonzo
gr8gonzo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of N M

ASKER

Thank you very much!