-2

I am working on a application that checks the health status of external services (API's etc). To display the health statuses I need make an API call for every service there is.

I am having trouble retrieving the result of the API calls using asynchronous functions.

I have two methods to retrieve the information of the API endpoints. But I can't figure out why it is not working.

public async Task<List<HealthStatus>> ExecuteApiCallsAsync()
{
    var apis = new[] {
         new { Name = "API 1", Url = "https://localhost:7157/api/healthstatus" },
         new { Name = "API 2", Url = "https://localhost:7150/api/healthstatus" }
    };

    var tasks = new List<Task<HealthStatus>>();

    try
    {
        //    for(int i = 0; i < apis.Length; i++)
        //    {
        //        //tasks[i] = GetApiHealthStatusAsync(apis[i].Name, apis[i].Url);
        //        //tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
        //    }
        foreach (var api in apis)
        {
            tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
        }

        Task.WaitAll(tasks.ToArray());
        
        return tasks.ToList();
    }
    catch (Exception ex)
    {
    }
}

public async Task<HealthStatus> GetApiHealthStatusAsync(string apiName, string apiUrl)
{
    var healthStatus = new HealthStatus { Name = apiName };

    try
    {
        using var client = new HttpClient();
        var result = await client.GetAsync(apiUrl);

        if (result != null && result.IsSuccessStatusCode)
        {
            var content = await result.Content.ReadAsStringAsync();
            healthStatus = JsonConvert.DeserializeObject<HealthStatus>(content);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        healthStatus.Condition = "Unhealthy";
    }
    return healthStatus;
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
N D
  • 1
  • 5
    Empty `catch` blocks are an unhealthy sign. They're how you tell the system "I don't care about any errors here" and since apparently you're having some problems with some (unmentioned as yet) errors, they probably don't belong in your code. – Damien_The_Unbeliever Mar 22 '23 at 15:26
  • 1
    What is the problem that you have? Could you provide more details? Also please mention the .NET platform and version that you are targeting (.NET Framework?, .NET 7?). – Theodor Zoulias Mar 23 '23 at 00:18
  • That should produce warnings. Read them. – Aluan Haddad Mar 23 '23 at 06:46

1 Answers1

0

It seems that the issue is with the following line of code:

return tasks.ToList(); tasks is a list of Task objects, and calling ToList() on it will simply create a new list with the same Task objects. To actually retrieve the results of the tasks, you need to call the Result property on each Task object.

One way to do this is to use the await Task.WhenAll(tasks) method instead of Task.WaitAll(tasks.ToArray()). This will wait for all the tasks to complete and return their results as an array of HealthStatus objects.

Here's the modified ExecuteApiCallsAsync method:

public async Task<List<HealthStatus>> ExecuteApiCallsAsync()
{
    var apis = new[] {
         new { Name = "API 1", Url = "https://localhost:7157/api/healthstatus" },
         new { Name = "API 2", Url = "https://localhost:7150/api/healthstatus" }
    };

    var tasks = new List<Task<HealthStatus>>();

    try
    {
        foreach (var api in apis)
        {
            tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
        }

        var results = await Task.WhenAll(tasks);

        return results.ToList();
    }
    catch (Exception ex)
    {
        // Handle exception
        return null;
    }
}

Note that you should also handle exceptions properly, either by re-throwing them or returning null.