Send HTTP POST message in ASP.NET Core using HttpClient PostAsJsonAsync
I want to send dynamic object like
new { x = 1, y = 2 };
as body of HTTP POST message. So I try to write
var client = new HttpClient();
but I can't find method
client.PostAsJsonAsync()
So I tried to add Microsoft.AspNetCore.Http.Extensions package to project.json and add
using Microsoft.AspNetCore.Http.Extensions;
to uses clause. However It didn't help me.
So what is the easiest way to send POST request with JSON body in ASP.NET Core?
Solution 1:
You should add reference to "Microsoft.AspNet.WebApi.Client" package (read this article for samples).
Without any additional extension, you may use standard PostAsync
method:
client.PostAsync(uri, new StringContent(jsonInString, Encoding.UTF8, "application/json"));
where jsonInString
value you can get by calling JsonConvert.SerializeObject(<your object>);
Solution 2:
I use this class:
public class JsonContent : StringContent
{
public JsonContent(object obj) :
base(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json")
{ }
}
Sample of usage:
new HttpClient().PostAsync("http://...", new JsonContent(new { x = 1, y = 2 }));
Solution 3:
I would add to the accepted answer that you would also want to add the Accept
header to the httpClient
:
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Solution 4:
Microsoft now recommends using an IHttpClientFactory
with the following benefits:
- Provides a central location for naming and configuring logical
HttpClient
instances. For example, a client named github could be registered and configured to access GitHub. A default client can be registered for general access. - Codifies the concept of outgoing middleware via delegating handlers
in
HttpClient
. Provides extensions for Polly-based middleware to take advantage of delegating handlers inHttpClient
. - Manages the pooling and lifetime of underlying
HttpClientMessageHandler
instances. Automatic management avoids common DNS (Domain Name System) problems that occur when manually managingHttpClient
lifetimes. - Adds a configurable logging experience (via
ILogger
) for all requests sent through clients created by the factory.
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1
Setup:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
// Remaining code deleted for brevity.
POST example:
public class BasicUsageModel : PageModel
{
private readonly IHttpClientFactory _clientFactory;
public BasicUsageModel(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task CreateItemAsync(TodoItem todoItem)
{
var todoItemJson = new StringContent(
JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
Encoding.UTF8,
"application/json");
var httpClient = _clientFactory.CreateClient();
using var httpResponse =
await httpClient.PostAsync("/api/TodoItems", todoItemJson);
httpResponse.EnsureSuccessStatusCode();
}
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#make-post-put-and-delete-requests
Solution 5:
If you are using .NET 5 or above, you can (and should) use the PostAsJsonAsync
extension method from System.Net.Http.Json:
httpClient.PostAsJsonAsync(url, new {
x = 1,
y = 2
});
If you are using an older version of .NET Core, you can implement the extension function yourself:
public static class HttpClientExtensions
{
public static Task<HttpResponseMessage> PostJsonAsync(this HttpClient httpClient, string url, object body)
{
var bodyJson = JsonSerializer.Serialize(body);
var stringContent = new StringContent(bodyJson, Encoding.UTF8, "application/json");
return httpClient.PostAsync(url, stringContent);
}
}