Hello,
In my current solution, a user triggers my web API from a web application first, then my web API calls the 3rd party web service, and the results/codes are displayed on the web application. This current design (web application <-> web API <-> 3rd party web service) forces the user to stay in front of the screen and keep constantly sending requests to the API until successfully fulfilling 20K codes. I want to call a web API in the background with IHostedService. I am not familiar with using Parallel.ForEachAsync
. How can I implement it into my IHostedService while calling this web API?
Here is the sample IHostedService:
public class BusinessService : IHostedService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
public BusinessService(IHttpClientFactory httpClientFactory, IHostApplicationLifetime applicationLifetime,
IConfiguration configuration, ILogger<BusinessService> logger)
{
_httpClientFactory = httpClientFactory;
_applicationLifetime = applicationLifetime;
_configuration = configuration;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Application starts: ");
//await MakeRequestsToRemoteService();
await GetData();
//Stop Application
_applicationLifetime.StopApplication();
_logger.LogInformation("Application stops: ");
}
private async Task MakeRequestsToRemoteService(string productCode, long id)
{
try
{
var httpClient = _httpClientFactory.CreateClient("GameClient");
var authenticationBytes = Encoding.ASCII.GetBytes("Test:R08GO1234^");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(authenticationBytes));
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("productCode", productCode),
new KeyValuePair<string, string>("quantity", "1"),
});
using var response = await httpClient.PostAsync(_configuration["Service:Production"], content);
if ((int) response.StatusCode == 200)
{
var coupons = await response.Content.ReadAsAsync<Root>();
_logger.LogInformation("Order {referenceId} {pin}, {Serial} ", coupons.ReferenceId,
coupons.Coupons[0].Pin, coupons.Coupons[0].Serial);
await UpdateData(coupons, id);
}
else
{
_logger.LogError("Game Code Service Application Error {statusCode} for {productCode}",
(int) response.StatusCode, productCode);
}
}
catch (Exception e)
{
_logger.LogError("Error: {Error} ", e.Message);
throw;
}
}
private async Task GetData()
{
var connString = _configuration["ConnectionStrings:Production"];
await using var sqlConnection = new SqlConnection(connString);
sqlConnection.Open();
await using var command = new SqlCommand {Connection = sqlConnection};
const string sql = @"Select top 100 id, customerId, firstName, LastName, phone, productCode, productName from TestOrders where status = 0 ORDER BY NEWID()";
command.CommandText = sql;
try
{
await using var reader = await command.ExecuteReaderAsync();
while (reader.Read())
{
_logger.LogInformation(
"Order {ID} {CustomerId}, {Name} {LastName}, {Phone}, {ProductCode}, {ProductName} ",
reader.GetInt64(0), reader.GetInt32(1), reader.GetString(2), reader.GetString(3),
reader.GetString(4), reader.GetString(5), reader.GetString(6));
await MakeRequestsToRemoteService(reader.GetString(5).Trim(), reader.GetInt64(0));
}
}
catch (SqlException exception)
{
_logger.LogError("Error: {Error} ", exception.Message);
throw; // Throw exception if this exception is unexpected
}
}
private async Task UpdateData(Root root, long id)
{
var connString = _configuration["ConnectionStrings:Production"];
await using var sqlConnection = new SqlConnection(connString);
sqlConnection.Open();
await using var command = new SqlCommand {Connection = sqlConnection};
const string sql = @"Update TestOrders set referenceId = @referenceId, Serial = @serial, Pin = @pin, status = 1 where id = @id";
command.CommandText = sql;
command.Parameters.Add(new SqlParameter("referenceId", root.ReferenceId));
command.Parameters.Add(new SqlParameter("serial", root.Coupons[0].Serial));
command.Parameters.Add(new SqlParameter("pin", root.Coupons[0].Pin));
command.Parameters.Add(new SqlParameter("id", id));
try
{
await command.ExecuteNonQueryAsync();
}
catch (SqlException exception)
{
_logger.LogError("Error: {Error} ", exception.Message);
throw; // Throw exception if this exception is unexpected
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}