Search code examples
c#.net-coreblazorblazor-client-sideblazor-webassembly

Blazor WebAssembly - appsettings.json as dependency while registering services


I'm trying to register my custom AppSettings class as a service but it's not working and I'm lost. I have the AppSettings class and the corresponding appsettings.json file located at wwwroot. Then I have another class that depends on the AppSettings class, ctor looking like this:

public GeneratorService(AppSettings appSettings)
{
    _appSettings = appSettings;
}

The Main method looks like this:

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("app");
    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    builder.Services.AddTransient(async sp =>
        {
            var httpClient = sp.GetRequiredService<HttpClient>();
            var response = await httpClient.GetAsync("appsettings.json");
            using var json = await response.Content.ReadAsStreamAsync();
            return await JsonSerializer.DeserializeAsync<AppSettings>(json);
        }
    );
    builder.Services.AddTransient<GeneratorService>();
    await builder.Build().RunAsync();
}

I know for sure that the JsonSerializer creates the correct instance of AppSettings from the file. I'm pretty new to this but from what I understand, it should work like this:

  1. I'm injecting GeneratorService to a .razor page so the page asks for GeneratorService instance
  2. GeneratorService has AppSettings in it's ctor so it asks for AppSettings instance
  3. Service provider knows that to get AppSettings instance it has to call HttpClient, read and deserialize the appsettings.json file

But when I try to load the mentioned .razor page, I'm getting this error:

Unhandled exception rendering component: Unable to resolve service for type 'BP.AppSettings' while attempting to activate 'BP.Services.GeneratorService'.

How come that the service provider can't create AppSettings and inject it into the GeneratorService? Thank you for your answers.


Solution

  • example appsettings.json

    {
      "ClientConfigurations": {
        "AzureAd": {
          "Authority": "https://login.microsoftonline.com/001f3bfc-XXXX-XXXX-XXX-17c0e6de3b0f",
          "ClientId": "815442365ec-xxxx-xxxx-xxxx-1ce9c3f3429",
          "ValidateAuthority": true
        }
      }
    }
    

    Add these classes. Note matching names.

        public class LocalConfigurations
        {
            public ClientConfigurations ClientConfigurations { get; set; }
        }
        public class ClientConfigurations
        {
            public AzureAdConfigurations AzureAd { get; set; }
        }
        public class AzureAdConfigurations
        {
            public string Authority { get; set; }
            public string ClientId { get; set; }
            public bool ValidateAuthority { get; set; }
        }
    

    In program.cs it is already loaded into builder.Configuration. These two lines should help you access it.

    var LocalConfigurations = builder.Configuration.Get<LocalConfigurations>();    
    builder.Services.AddSingleton(LocalConfigurations.ClientConfigurations);
    

    then in any component

    @page "/"
    @inject Models.ClientConfigurations config
    
    
    @config.AzureAd.ClientId
    

    enter image description here