POSTing JsonObject With HttpClient From Web API

466,076

Solution 1

With the new version of HttpClient and without the WebApi package it would be:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;

Or if you want it async:

var result = await client.PostAsync(url, content);

Solution 2

The easiest way is to use a StringContent, with the JSON representation of your JSON object.

httpClient.Post(
    "",
    new StringContent(
        myObject.ToString(),
        Encoding.UTF8,
        "application/json"));

Solution 3

Depending on your .NET version you could also use HttpClientExtensions.PostAsJsonAsync method.

https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions.postasjsonasync.aspx

Solution 4

If using Newtonsoft.Json:

using Newtonsoft.Json;
using System.Net.Http;
using System.Text;

public static class Extensions
{
    public static StringContent AsJson(this object o)
        => new StringContent(JsonConvert.SerializeObject(o), Encoding.UTF8, "application/json");
}

Example:

var httpClient = new HttpClient();
var url = "https://www.duolingo.com/2016-04-13/login?fields=";
var data = new { identifier = "username", password = "password" };
var result = await httpClient.PostAsync(url, data.AsJson())

Solution 5

I don't have enough reputation to add a comment on the answer from pomber so I'm posting another answer. Using pomber's approach I kept receiving a "400 Bad Request" response from an API I was POSTing my JSON request to (Visual Studio 2017, .NET 4.6.2). Eventually the problem was traced to the "Content-Type" header produced by StringContent() being incorrect (see https://github.com/dotnet/corefx/issues/7864).

tl;dr

Use pomber's answer with an extra line to correctly set the header on the request:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = client.PostAsync(url, content).Result;
Share:
466,076
Mark
Author by

Mark

My career focus has been the design, architecture, delivery, of Cloud services and Web applications. I have extensive experience with the Microsoft ecosystem and have been working with Azure since its initial release in 2008. -- • Deep technical understanding of Cloud strategy delivering from inception to implementation • Extensive knowledge of SaaS, PaaS, and IaaS from all major vendors • Proven track record providing consultation to SME, large enterprises, and the public sector • Practiced implementing and operating high-availability production environments • Experience architecting and implementing, large cloud migration and modernization projects

Updated on September 12, 2021

Comments

  • Mark
    Mark over 2 years

    I'm trying to POST a JsonObject using HttpClient from Web API. I'm not quite sure how to go about this and can't find much in the way of sample code.

    Here's what I have so far:

    var myObject = (dynamic)new JsonObject();
    myObject.Data = "some data";
    myObject.Data2 = "some more data";
    
    HttpClient httpClient = new HttpClient("myurl");
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
    HttpResponseMessage response = httpClient.Post("", ???);
    

    I think I need to cast my JsonObject as a StreamContent but I'm getting hung up on that step.

  • Zapnologica
    Zapnologica almost 9 years
    Take note on the content type. I left it out and had me debugging for much longer than I would like.
  • jle
    jle about 8 years
    Now found in Microsoft.AspNet.Client.WebApi nuget
  • Adriaan Davel
    Adriaan Davel about 8 years
    I just installed it from Microsoft.AspNet.WebApi.Client
  • Franklin Tarter
    Franklin Tarter about 7 years
    This solved my problem. I was messing around for a (long) while passing a C# class that contained some properties that were Lists using client.PostAsync, client.SendAsync.. I was getting very mixed results. If the array was empty my API solution would pick it up, but if the array had an item the controller method was not able to model bind the JSON. Thanks for this.. Seems to me that PostAsJsonAsync more reliably converts a complex C# object to JSON.
  • Zapnologica
    Zapnologica almost 7 years
    Is there a nuget package for this? I hate it when I transfer the project to a new machine, and this reference is always missing.
  • user3285954
    user3285954 almost 7 years
    Looking for this or something else? nuget.org/packages/Microsoft.AspNet.WebApi.Client
  • danatcofo
    danatcofo almost 7 years
    this is not asp.net core specific, its actually generic down to even 4.5.6
  • Captain Kenpachi
    Captain Kenpachi over 6 years
    That overloaded StringContent constructor did the trick for me.
  • Kiquenet
    Kiquenet about 6 years
    JsonConvert.SerializeObject issues using DateTimes ISO 8601 Kind: Local or UTC... hackered.co.uk/articles/…
  • Ruchira
    Ruchira about 6 years
    Think twice before calling Result on a Async method though blog.stephencleary.com/2012/07/dont-block-on-async-code.html
  • maxshuty
    maxshuty over 5 years
    For anyone who was tempted to throw this in a using like I was: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
  • Gail Foad
    Gail Foad over 5 years
    Thank you, anthls. var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json") was not enough. It needs content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); Thank you for saving my sanity.
  • bcr
    bcr over 5 years
    I put a using around the StringContent creation though.
  • anthls
    anthls over 5 years
    Using this answer I kept receiving a "400 Bad Request" response from an API I was POSTing my JSON request to (Visual Studio 2017, .NET 4.6.2). In addition to var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json") I had to set content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. See answer below for more details.
  • aruno
    aruno about 5 years
    PostAsJsonAsync is probably better if available to you - see @user3285954
  • Festus Martingale
    Festus Martingale about 5 years
    This worked great. Any reason why "application/json" needs to be set twice, one in the constructor and once via the property? Is it a bug?
  • anthls
    anthls about 5 years
    @FestusMartingale: good question! From my reading of the github issue (linked in the answer) the passing of "application/json" in the StringContent constructor is probably not required as it is being explicitly set on the resulting content.Headers.ContentType property. However, I haven't tested this in code.
  • Zeek2
    Zeek2 almost 5 years
    The synchronous approach shown above (i.e. using the Result attribute) can also be used for calls to ReadAsStringAsync e.g. string responseBody = /* await */ response.Content.ReadAsStringAsync().Result; ;)
  • Bertm13
    Bertm13 about 4 years
    It looks like the server does not support the full content type string. When you use the constructor without overriding the ContentType, it sets the value as application/json; charset=utf-8.
  • Phil Haselden
    Phil Haselden about 4 years
    Shouldn't you Dispose the StringContent instance though?
  • djack109
    djack109 about 4 years
    There appears to be a 25MB limit. Any ideas ?
  • miki
    miki over 3 years
    That is because first example is blocking call, and second works as continuation. Maybe this explanation helps
  • Saturn K
    Saturn K over 2 years
    @maxshuty, wrapping HttpClient in a using block would work for cases where you're only ever using it in that block. If you wanted to re-use it or use it to call a different endpoint, it would re-instantiate the HttpClient. Setting it to static would also work for cases where your HttpClient is only ever using one DNS. Depending on the .NET version, you may want to use an IHttpClientFactory for typed Clients and then registering that client as a singleton. Singleton in this case is better than static.