How to add data from async method in singleton in Startup.cs in net.core 3.0?

903 views Asked by At

I'm trying to get async data from HttpClient and add this data as singleton at ConfigureServices in Startup.cs

public static class SolDataFill
{
    static HttpClient Client;

    static SolDataFill()
    {
        Client = new HttpClient();
    }

    public static async Task<SolData> GetData(AppSettings option)
    {
        var ulr = string.Format(option.MarsWheaterURL, option.DemoKey);
        var httpResponse = await Client.GetAsync(ulr);

        var stringResponse = await httpResponse.Content.ReadAsStringAsync();

        var wheather = JsonConvert.DeserializeObject<SolData>(stringResponse);
        return wheather;
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration);
    var settings = Configuration.GetSection("NasaHttp") as AppSettings;
    var sData = await SolDataFill.GetData(settings);
    services.AddSingleton<SolData>(sData);
}

There is an error: it's possible to use await with async only. How to add data from async method to singleton?

1

There are 1 answers

0
Martin On

Maybe you should consider to rework your SolDataFill to end up as a DataService instead of adding everything to the DI container.

Then everybody who needs the data can query for it. (This is why I have added the cache here to not always do a request)

public class SolDataFill
{
    private readonly HttpClient _client;
    private readonly AppSettings _appSettings;
    private readonly ILogger _logger;
    
    private static SolData cache;
    
    public SolDataFill(HttpClient client, AppSettings options, ILogger<SolDataFill> logger)
    {
        _client = client;
        _appSettings = options;
        _logger = logger;
    }

    public async Task<SolData> GetDataAsync()
    {
        if(cache == null)
        {
            var ulr = string.Format(_appSettings.MarsWheaterURL, _appSettings.DemoKey);
            _logger.LogInformation(ulr);
            var httpResponse = await _client.GetAsync(ulr);
            if(httpResponse.IsSuccessStatusCode)
            {
                _logger.LogInformation("{0}", httpResponse.StatusCode);
                var stringResponse = await httpResponse.Content.ReadAsStringAsync();
                cache = JsonConvert.DeserializeObject<SolData>(stringResponse);
                return cache;
            }
            else
            {
                _logger.LogInformation("{0}", httpResponse.StatusCode);
            }
        }
        return cache;
    }
}

Full example can be found here

Like written in the comments of your question its very simple to run a async method synchronous by just GetAwaiter().GetResult(). But in my optinion everytime I see this code I personally think there is a code smell hidden which can be refactored.