Hi I have a requirement where in I have to call two different client methods from same api in .NET Core and I have structured my code as follows. THis is working fine but Please give me your valuable inputs or suggestions for improvements.
I am using HTTPClientFactory to create my clients as shown below:
public class CustomerApiClient : ICustomerApiClient
{
private readonly HttpClient _httpClientCustomer;
private readonly HttpClient _httpClientProduct;
private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _configuration;
public CustomerApiClient(IHttpClientFactory httpClientFactory, IConfiguration configuration, ILogger<CustomerApiClient> logger)
{
this._logger = logger;
this._httpClientFactory = httpClientFactory;
this._configuration = configuration;
_httpClientCustomer = httpClientFactory.CreateClient("CustomerService");
var authApiKey = configuration.GetSection("CustomerAuthApiKey")?.Value;
_httpClientCustomer.DefaultRequestHeaders.Add("AuthApiKey", authApiKey);
_httpClientProduct = httpClientFactory.CreateClient("ProductService");
var authApiKeyImageManagementService = configuration.GetSection("ProductAuthApiKey")?.Value;
_httpClientProduct.DefaultRequestHeaders.Add("AuthApiKey", authApiKeyImageManagementService);
}
public virtual async Task<object> GetCustomerDetailsAsync(int customerId)
{
_logger.LogDebug("customerId");
var uri = string.Concat(_httpClientCustomer?.BaseAddress, $"/GetCustomerBycustomerId?customer={customerId}");
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri))
{
using (var response = await _httpClientCustomer.SendAsync(requestMessage, CancellationToken.None))
{
var stream = await response.Content.ReadAsStreamAsync();
var strStream = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
if (strStream.ToLower() == "null")
{
return null;
}
JObject respJobject = JObject.Parse(strStream);
var resultCustomer = respJobject;
}
}
}
// the resultCustomer object wil have productId in it. Will be using the productId for below service -- /product/productId . Have not written the code for it so hardcoded it as 1102
var uriProductService = string.Concat(_httpClientProduct?.BaseAddress, $"/product/1102");
using (var requestMessage1 = new HttpRequestMessage(HttpMethod.Get, uriProductService))
{
using (var response = await _httpClientProduct.SendAsync(requestMessage1, CancellationToken.None))
{
var stream1 = await response.Content.ReadAsStreamAsync();
var strStream1 = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
return ApiHelper.DeserializeJson<System.Collections.Generic.ICollection<Product>>(stream1);
}
var content = await ApiHelper.StreamToStringAsync(stream1);
throw new ApiException
{
StatusCode = (int)response.StatusCode,
Content = content
};
}
}
}
}
My Startup.cs file contains the following in ConfigureDependencies method
serviceCollection.AddHttpClient("CustomerService", im =>
{
im.BaseAddress = new Uri("https://Testserver-Phse2.net/Shared/CustomerService/api/v1/Customers");
});
serviceCollection.AddHttpClient("ProductService", dc =>
{
dc.BaseAddress = new Uri(Configuration.GetSection("ApiUrls:ProductServiceApi")?.Value);
});
serviceCollection.AddScoped<ICustomerApiClient, CustomerApiClient>();
And if you observe this line JObject respJobject = JObject.Parse(strStream);
I am converting my stream to JObject and then using linq to loop through it. Is it a good thing or should I create a localized DTO Customer object and deserialize into it like shown below.. Which approach is better in terms of optimization
var objectResponse_ = ApiHelper.DeserializeJson<Customer>(stream)
ApiHelper.cs
public static class APiHelper
public static T DeserializeJsonFromStream<T>(Stream stream)
{
if (stream == null || !stream.CanRead)
return default(T);
using (var sr = new StreamReader(stream))
using (var jtr = new JsonTextReader(sr))
{
var js = new JsonSerializer();
js.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
var searchResult = js.Deserialize<T>(jtr);
return searchResult;
}
}
}