You can use:
// return HttpResponseMessage
var res= await httpClient.GetAsync<List<Car>>("/api/cars")
if (res.IsSuccessStatusCode)
var cars = res.Content.ReadFromJsonAsync<List<Car>>();
else
// deal with the HttpResponseMessage directly as you used to
I use a base class like this:
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace MyProject.ClientAPI
{
public abstract class ClientAPI
{
protected readonly HttpClient Http;
private readonly string BaseRoute;
protected ClientAPI(string baseRoute, HttpClient http)
{
BaseRoute = baseRoute;
Http = http;
}
protected async Task<TReturn> GetAsync<TReturn>(string relativeUri)
{
HttpResponseMessage res = await Http.GetAsync($"{BaseRoute}/{relativeUri}");
if (res.IsSuccessStatusCode)
{
return await res.Content.ReadFromJsonAsync<TReturn>();
}
else
{
string msg = await res.Content.ReadAsStringAsync();
Console.WriteLine(msg);
throw new Exception(msg);
}
}
protected async Task<TReturn> PostAsync<TReturn, TRequest>(string relativeUri, TRequest request)
{
HttpResponseMessage res = await Http.PostAsJsonAsync<TRequest>($"{BaseRoute}/{relativeUri}", request);
if (res.IsSuccessStatusCode)
{
return await res.Content.ReadFromJsonAsync<TReturn>();
}
else
{
string msg = await res.Content.ReadAsStringAsync();
Console.WriteLine(msg);
throw new Exception(msg);
}
}
}
}
and then from derived class, we’re back to the one-liner
public class MySpecificAPI : ClientAPI
{
public MySpecificAPI(HttpClient http) : base("api/myspecificapi", http) {}
public async Task<IEnumerable<MyClass>> GetMyClassAsync(int ownerId)
{
try
{
return GetAsync<IEnumerable<MyClass>>($"apiMethodName?ownerId={ownerId}");
}
catch (Exception e)
{
// Deal with exception
}
}
// repeat for post
}
UPDATE: HANDLING NULL RETURNS
Having encountered a valid scenario where the WebAPI returns null, the line:
return await res.Content.ReadFromJsonAsync<TReturn>();
will throw a Json Deserialization error.
To address this, we need to detect NoContent response (204) and handle accordingly:
if (res.StatusCode == HttpStatusCode.NoContent)
return default(TReturn);
else if (res.IsSuccessStatusCode)
return await res.Content.ReadFromJsonAsync<TReturn>();