0
votes

I'm using Blazor WebAssembly 3.2.0 Preview 3 / Static / Client Side

I'm now using #if DEBUG #else #endif for the string variable "backendUrl". I'd like to load that setting from appsettings.{environment}.json.

I can get the config after var host = builder.Build(); (info from Microsoft Docs, see sample code below, and link here above) but the gRPC service is called before that.

More info about appsetting.{environment}.json in Blazor WebAssembly 3.2.0 Preview 3

My question: is it possible or should I keep using #if DEBUG etc.
(I'd like to use appsettings whenever it is possible anywhere in my code.)

Part of my Program.cs

    string backendUrl = string.Empty;
#if DEBUG
    backendUrl = "https://localhost:5001"; // Local debug URL
#else
    backendUrl = "https://<example>.com:5001"; // Production URL
#endif
    builder.Services.AddSingleton(services =>
    {
        // Create a gRPC-Web channel pointing to the backend server.
        // GrpcWebText is used because server streaming requires it. If server streaming is not used in your app
        // then GrpcWeb is recommended because it produces smaller messages.
        var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));
        var channel = GrpcChannel.ForAddress(backendUrl, new GrpcChannelOptions { HttpClient = httpClient });
        return channel;
    });

    // load settings from appsettings.{environment}.json
    // see: https://docs.microsoft.com/en-us/aspnet/core/blazor/dependency-injection?view=aspnetcore-3.1#add-services-to-an-app
    var host = builder.Build();

    var backendDomain = host.Configuration["Settings:BackEndDomain"];
    Console.WriteLine($"Backend Domain: {backendDomain}");

    await host.RunAsync();

    // original
    // await builder.Build().RunAsync();
2

2 Answers

1
votes

I also posted this question at GitHub dotnet/aspnetcore and James Newton-King came up with the answer, see: https://github.com/dotnet/aspnetcore/issues/20442#issuecomment-608064432

JamesNK:

You should be able to get an IConfiguration inside the AddSingleton. e.g.

builder.Services.AddSingleton(services =>
{
    var configuration = services.GetRequiredService<IConfiguration>();
    var backendUrl = configuration["BackendUrl"];

    // Create a gRPC-Web channel pointing to the backend server.
    // GrpcWebText is used because server streaming requires it. If server streaming is not used in your app
    // then GrpcWeb is recommended because it produces smaller messages.
    var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));
    var channel = GrpcChannel.ForAddress(backendUrl, new GrpcChannelOptions { HttpClient = httpClient });
    return channel;
});
1
votes

Based on Jaap's answer I had to do the following for Serilog BrowserHttp Sink endpoint

services.AddSingleton(provider =>
        {
            var config = provider.GetService<IConfiguration>();
            _appConfiguration = config.GetSection("App").Get<AppConfiguration>();

            var levelSwitch = new LoggingLevelSwitch();
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.ControlledBy(levelSwitch)
                .Enrich.WithProperty("InstanceId", Guid.NewGuid().ToString("n"))
                .WriteTo.BrowserHttp(_appConfiguration.ApiBaseUrl, controlLevelSwitch: levelSwitch)
                .WriteTo.BrowserConsole()
                .CreateLogger();

            Log.Information("Hello, browser!");

            return _appConfiguration;
        });