C# – Newtonsoft extension methods for HttpClient

System.Net.Http.Json provides extension methods that simplify getting and sending JSON with HttpClient. Internally, it uses System.Text.Json for serialization.

What if you want to use Newtonsoft instead of System.Text.Json? You can use the following extension methods for that:

using Newtonsoft.Json;

public static class NewtonsoftHttpClientExtensions
{
	public static async Task<T> GetFromJsonAsync<T>(this HttpClient httpClient, string uri, JsonSerializerSettings settings = null, CancellationToken cancellationToken = default)
	{
		ThrowIfInvalidParams(httpClient, uri);

		var response = await httpClient.GetAsync(uri, cancellationToken);

		response.EnsureSuccessStatusCode();

		var json = await response.Content.ReadAsStringAsync();

		return JsonConvert.DeserializeObject<T>(json, settings);
	}

	public static async Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient httpClient, string uri, T value, JsonSerializerSettings settings = null, CancellationToken cancellationToken = default)
	{
		ThrowIfInvalidParams(httpClient, uri);

		if (value is null)
		{
			throw new ArgumentNullException(nameof(value));
		}

		var json = JsonConvert.SerializeObject(value, settings);

		var response = await httpClient.PostAsync(uri, new StringContent(json, Encoding.UTF8, "application/json"), cancellationToken);

		response.EnsureSuccessStatusCode();

		return response;
	}

	private static void ThrowIfInvalidParams(HttpClient httpClient, string uri)
	{
		if (httpClient == null)
		{
			throw new ArgumentNullException(nameof(httpClient));
		}

		if (string.IsNullOrWhiteSpace(uri))
		{
			throw new ArgumentException("Can't be null or empty", nameof(uri));
		}
	}
}
Code language: C# (cs)

These are modeled off of the extension methods in System.Net.Http.Json. HttpClient is used to fetch the JSON content and then it’s deserialized to a model with Newtonsoft. You can pass in a JsonSerializerSettings object to change the serialization settings if necessary, and you can optionally pass in a CancellationToken object.

Example of using the extension methods

Here’s an example of using these extension methods:

var httpClient = new HttpClient();

var stock = await httpClient.GetFromJsonAsync<Stock>("https://localhost:12345/stocks/VTSAX");

Console.WriteLine($"Got stock {stock.Symbol}. Current price = {stock.Price}.");
stock.Price += 0.10m;

await httpClient.PostAsJsonAsync<Stock>("https://localhost:12345/stocks/", stock);

Console.WriteLine("Added 10 cents to the price");
Code language: C# (cs)

This outputs:

Got stock VTSAX. Current price = 109.
Added 10 cents to the priceCode language: plaintext (plaintext)

Modifying the getting/sending code

The source code for the System.Net.Http.Json extension methods is overly complicated (you can look at them in the open source .NET repository). After all, think about what these extension methods are doing: they are using a serializer and HttpClient.

If you’ve ever used HttpClient to get and send JSON without these extension methods, you’ve probably written the same few lines of boilerplate code over and over. All the extension methods are doing is abstracting away those few lines. This should be very simple and direct.

That’s the benefit of these Newtonsoft extension methods: they are simple and direct, so you can use them as is, or use them as a starting point and easily modify the getting / sending code if you want.

You could even use these as a starting point for extension methods that use System.Text.Json internally (swap out the Newtonsoft-specific types for System.Text.Json equivalents). It’d be difficult to modify the System.Net.Http.Json logic, so this is a good alternative.

Source code

You can find the source code, including unit tests and an example console app, in this repository: https://github.com/makolyte/newtonsoft.json.httpclient