Blazor Client-Side (WebAssembly) reading a json file on startup.cs

Viewed 4454

Since appsettings.json does not work very well with blazor WA, i am creating my own and putting a .json file in wwwroot, in the pages that require it, i use the HttpClient to get to the file as follow config = await Http.GetJsonAsync<Configuration>("/config/appsettings.json");

This works great, however I am doing this in multiple pages, so I would like to inject Configuration object/service at startup.cs and have my pages use that instead of doing this multiple times.

I am having a hard time finding out how to properly read the file in Startup.cs, any help would be appreciated.

UPDATE

It seems that App.OnInitializedAsync is being fired before Index.OnInitializedAsync but the Settings = await httpClient.GetJsonAsync<Settings>("/config/appsettings.json").ConfigureAwait(false); taking longer which is causing App.OnInitializedAsync to execute BEFORE the above line.

here is all the code

Startup.cs

    public class Startup
    {

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<ConfigurationManager>();
            services.AddBlazoredToast();
        }
        public void Configure(IComponentsApplicationBuilder app)
        {
            app.AddComponent<App>("app");
        }

    }

App.razor

    protected override async Task OnInitializedAsync()
    {

        Console.WriteLine("App.OnInitializedAsync");
        await configManager.InitializeAsync();

    }

Index.razor


    protected override async Task OnInitializedAsync()
    {
        Console.WriteLine("Index.OnInitializedAsync");


        //config = await Http.GetJsonAsync<Configuration>("/config/appsettings.json");
        if (configManager == null)
        {
            Console.WriteLine("Index.OnInitializedAsync config manager is null");
        }
        else
        {
            if (configManager.Settings == null)
            {
                Console.WriteLine("Index.OnInitializedAsync config.Settings is null");
            }
            else
            {
                Console.WriteLine("base url" + configManager.Settings.ApiBaseUrl);

            }
        }
    }

Here is the sequence

WASM: App.OnInitializedAsync
WASM: ConfigurationManager.InitializeAsync
WASM: Index.OnInitializedAsync
WASM: Index.OnInitializedAsync config.Settings is null
WASM: ConfigurationManager.Setting has been set: ApiBaseUrl https://localhost:44316 
1 Answers

The best way IMHO is to register a singleton Task

        public void ConfigureServices(IServiceCollection services)
        {
            services
                .AddSingleton(async p =>
                {
                    var httpClient = p.GetRequiredService<HttpClient>();
                    Console.WriteLine("Get settings called");
                    return await httpClient.GetJsonAsync<Settings>("settings.json")
                        .ConfigureAwait(false);
                });
        }

And call in with async where you need settings. In page for sample

@inject Task<Settings> _getSettings

...

@code {
    protected override async Task OnInitializedAsync()
    {
        var settings = await _getSettings;
        Console.WriteLine("Settings received in main {0}", settings?.ApiBaseUrl);
    }
}

This way the call to settings.json is made just once

Related