How to send a Post body in the HttpClient request in Windows Phone 8?
Asked Answered
T

3

127

I have written the code below to send headers, post parameters. The problem is that I am using SendAsync since my request can be GET or POST. How can I add POST Body to this peice of code so that if there is any post body data it gets added in the request that I make and if its simple GET or POST without body it send the request that way. Please update the code below:

HttpClient client = new HttpClient();

// Add a new Request Message
HttpRequestMessage requestMessage = new HttpRequestMessage(RequestHTTPMethod, ToString());

// Add our custom headers
if (RequestHeader != null)
{
    foreach (var item in RequestHeader)
    {

        requestMessage.Headers.Add(item.Key, item.Value);

    }
}

// Add request body


// Send the request to the server
HttpResponseMessage response = await client.SendAsync(requestMessage);

// Get the response
responseString = await response.Content.ReadAsStringAsync();
Tit answered 6/8, 2014 at 10:50 Comment(1)
Please see updated answer, it has a nicer approach.Corey
C
229

UPDATE 2:

From @Craig Brown:

As of .NET 5 you can do:
requestMessage.Content = JsonContent.Create(new { Name = "John Doe", Age = 33 });

See JsonContent class documentation

UPDATE 1:

Oh, it can be even nicer (from this answer):

requestMessage.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}", Encoding.UTF8, "application/json");

This depends on what content do you have. You need to initialize your requestMessage.Content property with new HttpContent. For example:

...
// Add request body
if (isPostRequest)
{
    requestMessage.Content = new ByteArrayContent(content);
}
...

where content is your encoded content. You also should include correct Content-type header.

Corey answered 6/8, 2014 at 11:13 Comment(3)
How to write a Json using a jsonSerializer into the content?Chamkis
@Chamkis I use the Newtonsoft.Json package to do it like so: requestMessage.Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); You could also use you JsonSerializer to serialize into a string as you might currently be doing, and then pass that string as the first parameter to the StringContent constructor.Suter
As of .NET 5 you can do: requestMessage.Content = JsonContent.Create(new {Name = "John Doe", Age = 33});Kanya
O
17

I implemented it in the following way. I wanted a generic MakeRequest method that could call my API and receive content for the body of the request - and also deserialise the response into the desired type. I create a Dictionary<string, string> object to house the content to be submitted, and then set the HttpRequestMessage Content property with it:

Generic method to call the API:

    private static T MakeRequest<T>(string httpMethod, string route, Dictionary<string, string> postParams = null)
    {
        using (var client = new HttpClient())
        {
            HttpRequestMessage requestMessage = new HttpRequestMessage(new HttpMethod(httpMethod), $"{_apiBaseUri}/{route}");

            if (postParams != null)
                requestMessage.Content = new FormUrlEncodedContent(postParams);   // This is where your content gets added to the request body


            HttpResponseMessage response = client.SendAsync(requestMessage).Result;

            string apiResponse = response.Content.ReadAsStringAsync().Result;
            try
            {
                // Attempt to deserialise the reponse to the desired type, otherwise throw an expetion with the response from the api.
                if (apiResponse != "")
                    return JsonConvert.DeserializeObject<T>(apiResponse);
                else
                    throw new Exception();
            }
            catch (Exception ex)
            {
                throw new Exception($"An error ocurred while calling the API. It responded with the following message: {response.StatusCode} {response.ReasonPhrase}");
            }
        }
    }

Call the method:

    public static CardInformation ValidateCard(string cardNumber, string country = "CAN")
    { 
        // Here you create your parameters to be added to the request content
        var postParams = new Dictionary<string, string> { { "cardNumber", cardNumber }, { "country", country } };
        // make a POST request to the "cards" endpoint and pass in the parameters
        return MakeRequest<CardInformation>("POST", "cards", postParams);
    }
Outman answered 13/6, 2018 at 15:37 Comment(4)
Couple of problems with this implementation. First, it is not async. The use of ".Result" causes this to be a blocking call. Second problem is it doesn't scale! See my answer on why here - #22561471 Third problem is you are throwing exceptions to handle control-flow. This is not a good practice. See - learn.microsoft.com/en-us/visualstudio/profiling/…Washstand
Thanks for the input. I'll check those linksOutman
@AdamHey its good for synchronous requests, thanks!Ranna
Also, you've got a memory leak. HttpRequestMessage implements IDisposable so you need to wrap it in a usingBurkhardt
C
0

I did create a method:

public static StringContent GetBodyJson(params (string key, string value)[] param)
    {
        if (param.Length == 0)
            return null;

        StringBuilder builder = new StringBuilder();

        builder.Append(" { ");

        foreach((string key, string value) in param)
        {
            builder.Append(" \"" + key + "\" :"); // key
            builder.Append(" \"" + value + "\" ,"); // value
        }

        builder.Append(" } ");

        return new StringContent(builder.ToString(), Encoding.UTF8, "application/json");
    }

obs : Use StringContent in HttpContent, the inheritance is StringContent -> ByteArrayContent -> HttpContent.

Cenotaph answered 18/1, 2022 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.