In modern web development, sending JSON objects over HTTP has become a common practice for exchanging data between clients and servers. In this article, we will explore how to send a JSON object using HttpClient.
With that, let’s get started.
Preparation to Send a JSON Object Using HttpClient
To start, let’s define a simple DTO object for the responses we expect from the https://petstore.swagger.io/v2
API:
public class PetCategory { [JsonPropertyName("name")] public string? Name { get; set; } } public class PetDto { [JsonPropertyName("id")] public long Id { get; set; } [JsonPropertyName("category")] public PetCategory? Category { get; set; } [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("status")] public string? Status { get; set; } }
Initially, we define a category for the pet with the PetCategory
class that defines only a Name
property and use that in our PetDto
class. Additionally, along the Category
, we have an Id
, Name
and Status
property.
Send a JSON Object Using HttpClient and StringContent Class
In C#, it is easy to generate and send JSON Objects using HttpClient
class along with the StringContent
class while making API calls.
Let’s see this in an example:
new StringContent("{ \"status\": \"available\" }", Encoding.UTF8);
The constructor accepts a JSON string as the required first argument and an optional second argument being the encoding format.
Keeping this in our head, we can convert a C# object to a JSON string using JsonSerializer
class from the NuGet package System.Text.Json
. We can also use JsonConvert
class from Newtonsoft.Json
NuGet package, but we will focus on using JsonSerializer
class in our examples.
Send a JSON Object Using StringContent Class
Let’s use StringContent
, starting with an interface:
public interface IPetService { Task<PetDto?> PostAsStringContentAsync(); }
Firstly, we define an IPetService
interface with the PostAsStringContent()
method.
Next, let’s implement this interface:
public class PetService : IPetService { private readonly HttpClient _httpClient; public PetService(HttpClient httpClient) { _httpClient = httpClient; } public async Task<PetDto?> PostAsStringContentAsync() { var petData = CreatePet(); var pet = JsonSerializer.Serialize(petData); var request = new HttpRequestMessage(HttpMethod.Post, "pet"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(pet, Encoding.UTF8); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var createdPet = JsonSerializer.Deserialize<PetDto>(content); return createdPet; } private PetDto CreatePet() { return new PetDto { Name = "German Shepherd", Status = "Available", Category = new PetCategory { Name = "Canines" } }; } }
Firstly, we create a PetService
class and implement our interface IPetService
. Then, in our PostAsStringContentAsync()
method we implement a POST
request to create a new pet. Moreover, we create a new PetDto
object and serialize it into a JSON string using the JsonSerialization.Serialize()
method.
Then, we create an HttpRequestMessage
object for the POST request to the /pet
endpoint of our test API.
Furthermore, we pass the JSON string, pet
, as an argument to the constructor of StringContent
class, then this is assigned to the request.Content
variable. Additionally, we also define that the content is of type application/json
to indicate that we are sending JSON content. Moreover, the Accept
header we define, tells the server that our client accepts only application/json
content. We send the request asynchronously using the SendAsync()
method of the HttpClient
instance.
Following that, we receive an asynchronous response. Furthermore, we make sure with the EnsureSuccessStatusCode()
method that we continue with a successful response. Using the response object we read the response string using the ReadAsStringAsync()
method.
Finally, we deserialize the response content which is a JSON string into an object, createdPet
using the JsonSerializer.Deserialize()
method. The deserialized object is returned as the result of the service method.
Let’s have a look at how we register a HttpClient
instance:
builder.Services.AddHttpClient<IPetService, PetService>(client => { client.BaseAddress = new Uri("https://petstore.swagger.io/v2/"); });
In our Program
class we call the AddHttpClient()
method to register an instance for our PetService
. This method ensures that we efficiently use HttpClient instances for our class. Additionally, we set the BaseAddress
property for the instance to our https://petstore.swagger.io/v2
API.
HttpClient
in ASP.NET Core check out our tutorial HttpClient with ASP.NET Core Tutorial.Now, let’s register an API endpoint in our Program
class:
app.MapPost("/postAsStringContent", async (IPetService petService) => await petService.PostAsStringContent());
In the MapPost()
method, we add the API route postAsStringContent
in which we invoke the PostAsStringContentAsync()
method of our IPetService
.
Testing the PostAsStringContent Endpoint
Moving forward, let’s run our application make a POST request to our endpoint:
{ "id": 9223372036854776000, "category": { "name": "Canines" }, "name": "German Shepherd", "status": "Available" }
We execute our endpoint /postAsStringContent
and get a successful JSON response from the URL where we posted our pet object.
Send a JSON Object Using HttpClient and PostAsJsonAsync Method
With the advent of .NET 5 and higher versions, C# made sending POST
requests with JSON contents easier and the implementation simpler with fewer lines of code. It hides the process of serializing objects into JSON formats, setting the headers, and sending the request. Thereby making the code shorter and easier to read.
Let’s have a look at how we can leverage this method:
await _httpClient.PostAsJsonAsync("pet", petData);
All we need to do is pass our URL and the object that we would like to send as JSON to the method and that’s it.
Using the PostAsJsonAsync()
method, developers can focus on what they want to achieve instead of dealing with the technical details of HttpClient
.
We have to keep in mind that the PostAsJsonAsync()
method uses JsonSerializerDefaults.Web
option for serialization by default, unlike the JsonSerializer.Serialize()
method.
Send a JSON Object Using PostAsJsonAsync Method
Let’s enhance our PetService
code using this approach and showcase it in a new method:
public class PetService : IPetService { public async Task<PetDto?> PostAsJsonAsync() { var petData = CreatePet(); var response = await _httpClient.PostAsJsonAsync("pet", petData); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var createdPet = JsonSerializer.Deserialize<PetDto>(content); return createdPet; } }
We add the PostAsJsonAsync()
method to our IPetService
interface and the PetService
class. We re-use the CreatePet()
method to send the petData
object via the PostAsJsonAsync()
extension method for HttpClient
. The PostAsJsonAsync()
extension method encapsulates the serialization and setting of headers and contents. This is way cleaner and easier to read. Furthermore, we have significantly streamlined our code down to just six lines.
Now, let’s register a new API endpoint in our Program
class:
app.MapPost("/postAsJson", async (IPetService petService) => await petService.PostAsJsonAsync());
In the MapPost()
method, we register the API route postAsJson
where we invoke the PostAsJson()
method.
Testing the PostAsJson Endpoint
Once again, let’s run our application and make a POST request to our newly added endpoint:
{ "id": 9223372036854776000, "category": { "name": "Canines" }, "name": "German Shepherd", "status": "Available" }
We execute our newly implemented endpoint /postAsJson
and get a successful JSON response from the target URL.
Conclusion
In conclusion, C# makes it easy to send JSON objects using HttpClient methods. We demonstrated how to use JSON serialization to convert objects to JSON strings and send them over HTTP requests. Now we know how to send JSON objects without racking our brains.
And what if I wanna check how json was serialized