Как добавить данные из асинхронного метода в singleton в Startup.cs в net.core 3.0?

#c# #.net-core #asp.net-core-3.0

#c# #.net-ядро #asp.net-core-3.0

Вопрос:

Я пытаюсь получить асинхронные данные из HttpClient и добавить эти данные как одноэлементные в ConfigureServices в 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);
}
  

Возникает ошибка: можно использовать await только с async. Как добавить данные из асинхронного метода в singleton?

Комментарии:

1. Вы пробовали var sData = SolDataFill.GetData(settings).Resu< ?

2. Вы можете просто запустить этот метод синхронно, используя GetAwaiter().GetResult()

Ответ №1:

Возможно, вам следует подумать о том, чтобы переработать ваш SolDataFill , чтобы в конечном итоге стать сервисом данных, вместо того, чтобы добавлять все в контейнер DI.

Тогда все, кому нужны данные, могут запросить их. (Вот почему я добавил сюда кэш, чтобы не всегда выполнять запрос)

 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;
    }
}
  

Полный пример можно найти здесь

Как написано в комментариях к вашему вопросу, очень просто запустить асинхронный метод синхронно просто GetAwaiter().GetResult() . Но, по моему мнению, каждый раз, когда я вижу этот код, я лично думаю, что есть скрытый запах кода, который можно переработать.