appsettings.json
files and then maintain two copies. This is how I solved it.
If you add appsettings.json
to wwwroot
folder and take a look at the network tab in browser's dev tools you will notice that Blazor WASM actually retrieves it at the start:
That means it is possible to put another settings file that can be also shared with the server. Let's create a sharedsettings.json
:
To be able to merge it into appsettings.json
during runtime we need to modify Program.cs
like this:
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add("#app");
var http = new HttpClient()
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};
builder.Services.AddScoped(sp => http);
using var response = await http.GetAsync("sharedsettings.json");
using var stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
await builder.Build().RunAsync();
}
}
To be sure that this worked let's modify Index.razor
and display the setting:
@page "/"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
<h1>Hello, world!</h1>
<p>Shared setting: @(Configuration.GetValue<string>("SharedSection"))</p>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
The effect is satisfactory 😁
Because Blazor WASM is hosted by ASP.NET core backend then after publishing the solution the wwwroot
folder will be present in the main working path. A bit tricky thing is to add this shared json file to the server during debugging. That's why I decided to include it as a relative path to the file that is in the client project. I think the benefits justifies such a small inconvenience in the code. I modified my ASP.NET core Program.cs
file like this:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((_, config) =>
{
config.AddJsonFile("wwwroot/sharedsettings.json", optional: true, reloadOnChange: true); // When published
var absoluteDebugSharedSettingsPath = System.IO.Path.GetFullPath("../Client/wwwroot/sharedsettings.json");
config.AddJsonFile(absoluteDebugSharedSettingsPath, optional: true, reloadOnChange: true); // When debugging
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
});
}
To check if that's working in backend as well I modified the WeatherForecastController.cs
to look like this:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger _logger;
private readonly IConfiguration configuration;
public WeatherForecastController(ILogger logger, IConfiguration configuration)
{
_logger = logger;
this.configuration = configuration;
}
[HttpGet]
public IEnumerable Get()
{
return new List
{
new WeatherForecast
{
Date = DateTime.Now,
Summary = configuration.GetValue<string>("SharedSection"),
TemperatureC = 22
}
};
}
}
After compiling the weather forecast looks as expected 🎉
If you are having troubles following my steps then you can download example solution.
Comments
Michael Washington
Works great. Thanks for this.
Stephen Pham
Thanks! I got it to work in .NET 6 by making the following change in the ASP.NET core Program.cs file:
builder.Host.ConfigureAppConfiguration((_, config) =>
{
config.AddJsonFile("wwwroot/sharedsettings.json", optional: true, reloadOnChange: true); // When published
var absoluteDebugSharedSettingsPath = System.IO.Path.GetFullPath("../Client/wwwroot/sharedsettings.json");
config.AddJsonFile(absoluteDebugSharedSettingsPath, optional: true, reloadOnChange: true); // When debugging
});
Seem like a minor change, but it took me an hour or so to figure it out. :-)