Related to this question (and even this Stack Overflow's one) I have been trying to avoid blocking the code. So what I understood it's that is preferable to make all the methods that rely on an async one async themselve (thus not defeating the purpose of asynchronous). Therefore I have changed my code to do the following (I include here more "layers" than in the questions I linked as I had to change accordingly those).
My API, exposing a method:
[Route("api/postconfiguration")]
public async Task<IHttpActionResult> PostConfiguration(configurationData configurationData)
{
try
{
await _configurationRequestHandler.HandlePostRequest(configurationData);
return Ok();
}
catch (Exception e)
{
// Log error
return InternalServerError(e);
}
}
That uses this method:
public async Task HandlePostRequest(Data Data)
{
var configuration = await _ConfigurationService.GetConfigurationAsync(Data.AgentId);
// Use that configuration
}
And this would be the method calling the external api
public class ConfigurationApiClient : IConfigurationService
{
private readonly HttpClient _client;
private const string resourcePath = "configuration/{0}";
public ConfigurationApiClient(IConfigurationManager configurationManager)
{
_client = new HttpClient();
_client.BaseAddress = new Uri(configurationManager.GetAppSetting("ConfigurationApiUrl"));
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<Configuration> GetConfigurationAsync(int agentId)
{
try
{
var response = await _client.GetAsync(String.Format(resourcePath, agentId));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<Configuration>();
}
catch (HttpRequestException ex)
{
throw new Exception(string.Format("Exception when getting configuration for agent: {0}", agentId), ex);
}
}
}
This is my understanding of what I should do for making it asynchronous, but would appreciate if someone points me any error.
I am using the API on one client myself, which does this:
public async Task DeployConfiguration(Package package, EFEnvironment environment)
{
using (var client = new HttpClient())
{
// Prepare the configurationData
var agentTasks = agents.Select(a =>
{
var configurationPostRequest = new ConfigurationData
{
// Create it
};
return client.PostAsJsonAsync("api/postconfiguration", configurationPostRequest);
});
await Task.WhenAll(agentTasks);
}
}
Which is just called inside a sync method:
_deployApiService.DeployConfiguration(package, environment);