runtime: Why doesn't IConfigurationProvider have an async Load method?

This might be a small or silly thing to ask about/for, but why isn’t IConfigurationProvider.Load() async, returning a Task? Most configuration loading is going to be async, for example getting something from the filesystem or from the network. Now implementors are forced to use GetAwaiter().GetResult() in this method.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 70
  • Comments: 25 (4 by maintainers)

Most upvoted comments

Hi, any update on this?

We are missing this option as well. We’re loading configuraition from http endpoint and would be really nice if we could use async here.

Thanks

I’ve just encountered this as well - we want to have our appsettings.json use paths to secrets in AWS Secrets Manager - with a custom IConfigurationSource and ConfigurationProvider, we are able to resolve those paths to actual secrets but should be able to do so asynchronously.

There’s already an API proposal for an async configuration provider: https://github.com/dotnet/runtime/issues/79193

Maybe we could try to vote and comment over there to give it some momentum. 🤞

What’s the status of the issue? Almost every configuration provider is async in some way, so this would benefit a lot of providers. Even file providers should take advantage of an async provider.

Synchronously waiting for a Task result might be fine in a lot of scenarios (like ASP.NET) but is not possible for Blazor apps. This is a huge drawback if you want to load any remote configuration. Loading remote configurations is extremely common in client side apps, it’s almost a must have.

I’ve implemented an async adaptor over here

I’ll put this in the backlog, but it’s a fairly high-cost change since it would be extremely viral. It would mean adding ConfigurationBuilder.BuildAsync, which would again propagate up to the callers.

It is possible to use an async provider without the virality, but you have to create an instance of the async provider first and call InitialiseAsync() on it to prefetch the initial values, prior to adding to ConfigurationBuilder. That way when ConfigurationBuilder.Build is called the provider can return its prefetched config synchronously. The other aspect is to write an async version of ChangeToken.OnChange -> this allows the provider to handle change token reloads asynchronously.

I’m using Vault for getting secrets via http so async implementation is very useful such this scenarios.

FWIW I just ran into this with internal code at my employer. I also would like to see this have async APIs.

@maryamariyan it’s really simple example. We are storing our configuration within the DB, so when we want to load it in async manner we call GetAwaiter().GerResult() in Load and TryGet methods.

public class OurConfigurationProvider : ConfigurationProvider
{
    public override void Load()
    {
      Data = _db.GetConfigurationsAsync().GetAwaiter().GerResult();
    }

    public override bool TryGet(string key, out string value)
    {
      if (!Data.Contains(key))
      {
        var configuration = _db.GetConfigurationAsync(key).GetAwaiter().GerResult();
        if (configuration != null)
        {
          Data[key] = configuration;
        }
      }
        
      value = Data[key];
      return true;
    }
}

so it would be cool to do it async like:

    public class OurConfigurationProvider : ConfigurationProvider
    {
      public override async Task LoadAsync()
      {
        Data = await _db.GetConfigurationsAsync();
      }

      public override async Task<string> GetAsync(string key)
      {
        if (!Data.ContainsKey(key))
        {
          var configuration = await _db.GetConfigurationAsync(key);
          if (configuration != null)
          {
            Data[key] = configuration;
          }
          else
          {
            return null;
          }
        }
        return Data[key];
      }
    }