I've used a custom wrapper for calling asp.net web API services in some projects. I just wanted to share it over here. It's been tested for hundreds of times!
public class MyCustomWrapper<T> where T : class { private static readonly HttpClient Client = new HttpClient(); public async Task<T> GetItemAsync(string apiUrl, CancellationToken cancellationToken) { var result = default(T); try { var response = await Client.GetAsync(apiUrl, cancellationToken).ConfigureAwait(false); if (response.IsSuccessStatusCode) { await response.Content.ReadAsStringAsync().ContinueWith(x => { if (typeof(T).Namespace != "System") { var data = x?.Result; result = JsonConvert.DeserializeObject<T>(data); } else result = (T)Convert.ChangeType(x?.Result, typeof(T)); }, cancellationToken); } else { var content = await response.Content.ReadAsStringAsync(); response.Content?.Dispose(); throw new HttpRequestException($"{response.StatusCode}:{content}"); } } catch (Exception) { return result; } return result; } public async Task<T[]> GetItemsRequestAsync(string apiUrl, CancellationToken cancellationToken) { T[] result = null; var response = await Client.GetAsync(apiUrl, cancellationToken).ConfigureAwait(false); if (response.IsSuccessStatusCode) { await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) => { result = JsonConvert.DeserializeObject<T[]>(x.Result); }, cancellationToken); } else { var content = await response.Content.ReadAsStringAsync(); response.Content?.Dispose(); throw new HttpRequestException($"{response.StatusCode}:{content}"); } return result; } public async Task<T> PostRequestAsync(string apiUrl, T postObject, CancellationToken cancellationToken) { T result = default(T); var json = JsonConvert.SerializeObject(postObject); var content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); var response = await Client.PostAsync(apiUrl, content); if (response.IsSuccessStatusCode) { await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) => { result = JsonConvert.DeserializeObject<T>(x.Result); }, cancellationToken); } else { var unSuccesscontent = await response.Content.ReadAsStringAsync(); response.Content?.Dispose(); throw new HttpRequestException($"{response.StatusCode}:{unSuccesscontent}"); } return result; } public async Task PutRequestAsync(string apiUrl, T putObject, CancellationToken cancellationToken) { var response = await Client.PutAsync(apiUrl, new JsonContent(putObject), cancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); response.Content?.Dispose(); throw new HttpRequestException($"{response.StatusCode}:{content}"); } } public async Task DeleteRequestAsync(string apiUrl, CancellationToken cancellationToken) { var response = await Client.DeleteAsync(apiUrl, cancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync(); response.Content?.Dispose(); throw new HttpRequestException($"{response.StatusCode}:{content}"); } } } public class JsonContent : StringContent { public static JsonContent From(object data) => data == null ? null : new JsonContent(data); public JsonContent(object data) : base(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json") { } }
And about the usage of this wrapper:
var wrapperResult = new MyCustomWrapper<YourClass>(); var result = wrapperResult.GetItemAsync("https://localhost/api/user/GetInfo?username=" + "userName", new CancellationToken()); var data = result.Result;
that's it!