This is a quick and short tip on how to read and access the settings in appsettings.json and other custom configuration files into your Blazor application. I also explain how to use HttpClient
to load our custom configuration in our main program. I’m using Blazor WASM for this example.
Content
How to access appsettings.json
In this section, I will talk about the built-in configuration called appsettings.json which can be found in wwwroot directory of your project. In the event that appsettings.json is not created for you by the template, just create it manually in wwwroot directory.
In this example, I have a setting that contains a URL string. For instance, say, my appsettings.json looks like this:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"RestSvc": {
"ApiUrl": "http://localhost:5000/api/v2/Employees/"
}
}
And I want to read the value of the "ApiUrl"
key on line 7 because I want to use that URL string for my HTTP request to an API service; specifically, to send a request to delete an employee with a given email address.
Inject IConfiguration to read key-value pairs
To access the key-value pairs, it is actually simple and straightforward. In this example, I’m reading the configurations inside a button handler, HandleDeleteSubmit()
. You just need to do two things. First, inject IConfiguration
into your Blazor component, as shown below on line 6:
@page "/deleteemployees"
@page "/deleteemployees/{email}"
@using System;
@using System.Threading;
@inject IConfiguration configuration;
<button @onclick="HandleDeleteSubmit">
Delete
</button>
@code {
[Parameter]
public string? email{ get; set; }
private async Task HandleDeleteSubmit()
{
string restSvcApiUrl = configuration["RestSvc:ApiUrl"];
try
{
responseMessage = await httpClient.DeleteAsync(restSvcApiUrl+email);
}
catch(Exception ex)
{
System.Console.WriteLine("Exception: " + ex.Message);
}
}
}
Second, on line 18, call the configuration object with the string “RestSvc:ApiUrl” as key. As shown, above, the variable restSvcApiUrl
should now contain the string “http://localhost:5000/api/v2/Employees/”, which I can pass to DeleteAsync
method on line 22. And that’s it!
Next, I will talk about how to access your own custom configuration.
How to access custom configuration file
Let’s say you have a custom configuration file called messagesettings.json (also in wwwroot) which contains all of your message strings, and it looks like this:
{
"DeleteEmployee": {
"Ok": "Employee successfully deleted",
"NotOK": "Problem deleting employee"
}
}
And let’s say you want to use the values of "Ok"
and "NotOk"
under "DeleteEmployee"
in your program as messages after a successful or failed request to a REST API.
It’s not as simple as reading appsettings.json, though. To access and read a custom config file into your application takes a little bit more work. Fortunately, it’s a few lines in your main program.
Registering your custom configuration
So, what do you need to add to your main program? First, you need to load the messagesettings.json file and you need to do that inside your Program.cs file. Check out the code below.
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using RestClientTabular;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// To read a custom configuration file other than appsettings.json
// use HttpClient
var http = new HttpClient()
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress),
};
builder.Services.AddScoped(sp => http);
using var response = await http.GetAsync("messagesettings.json");
using var stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
await builder.Build().RunAsync();
First, use the namespace Microsoft.Extensions.Configuration as shown on line 5. Secondly, Lines 17-24 show you how to read your configuration into a Stream
, a sequence of bytes that represent your file.
According to a Microsoft documentation on configurations, you can’t directly access a configuration file because of a restriction placed on a client application (which makes sense), hence, we access configuration via HttpClient
. Line 17 shows you exactly this – a new HttpClient
is instantiated whose base address is the host where my Blazor application is running off of, in this case, it’s http://localhost:5163.
After loading your json file on line 22, you then read it into a Stream
object on line 23. Finally, on line 24, you then “register” your configurations so that you can use anywhere in your application via Injection.
Inject IConfiguration to read key-value pairs
To read key-value pairs in messagesetting.json, it’s no different from how we read appsettings.json from earlier.
@page "/deleteemployees"
@page "/deleteemployees/{email}"
@using System;
@using System.Threading;
@inject IConfiguration configuration;
<button @onclick="HandleDeleteSubmit">
Delete
</button>
@code {
[Parameter]
public string? email{ get; set; }
private async Task HandleDeleteSubmit()
{
string restSvcApiUrl = configuration["RestSvc:ApiUrl"];
try
{
responseMessage = await httpClient.DeleteAsync(restSvcApiUrl+email);
var deleteOkMessage = configuration["DeleteEmployee:Ok"];
}
catch(Exception ex)
{
var deleteNotOkMessage = configuration["DeleteEmployee:NotOk"];
System.Console.WriteLine("Exception: " + ex.Message);
}
}
}
As you might have noticed, this is the same button handler from earlier, except I added two lines – on line 23, I call configuration["DeleteEmployee:Ok"]
to get the value “Employee successfully deleted”. And on line 27, I call configuration["DeleteEmployee:NotOk"]
to get the value “Problem deleting employee"
.
Conclusion
The built-in configuration, appsettings.json, is loaded by Blazor by default, hence, accessing it is as simple as injecting IConfiguration
inside the Blazor component. For your own custom configuration file, you first need to load and read it into a Stream
object inside the main program using HttpClient
. Only then can you access the custom configurations in your Blazor component.
Hi Alejandrio Vasay,
Thanks for sharing this simple and useful trick to load configuration on blazor.
I have a problem on published website, if you change the appsettings.json file on the host, the app can’t read new data and we will get original data instead of changed data.
how to restart the blazor app or force to reload the appsettings.json?
Sorry to reply late, my blog is new and all comments are queued with spams :-). My answer to your question is specific to Blazor – works with either Blazor WASM or BlazorServer. The example applicaton that I will discuss below is actually a Blazor Server project created in Visual Studio. This project creates three components for you – Index, Counter, and FetchData. For example, I want to create a configuration that sets the homepage to one of these three components (or pages), so that whenever a new user visits (or when page is refreshed), they get a page I set in the configuration.
The way we solved this problem is through IOptionsSnapshot, and, generally, the steps are:
1. Define your sections in appsettings.json
2. Create a class that corresponds to this section
3. Change Program.cs to register your configuration
4. Inject IOptionsSnapshot in your code to access configuration.
1. DEFINE SECTION
First off, let’s say, your appsettings.json looks like this:
{
"AppOptions": {
"DefaultHomepage": "FetchData"
}
}
2. CREATE CLASS
What you’re going to want to do is create a corresponding class for this setting for example, create a AppOptions.cs inside Shared folder.
namespace BlazorServerApp2.Shared
{
public class AppOptions
{
public const string SectionName = "AppOptions";
public string? DefaultHomepage { get; set; }
}
}
3. REGISTER CONFIGURATION
In your Program.cs (or wherever you configure services), add this code:
//------------------------------------------------
// Register AppOptions section of appsettings.json
//------------------------------------------------
IConfiguration configuration = builder.Configuration;
builder.Services.Configure
4. INJECT IOptionsSnapshot
In the Index.razor, use the IOptionsSnapshot like so:
@page "/"
@using Microsoft.Extensions.Options
@inject IOptionsSnapshot
@if (appOptions.Value.DefaultHomepage == "")
{
}
else if(appOptions.Value.DefaultHomepage == "Counter")
{
}
else if(appOptions.Value.DefaultHomepage == "FetchData")
{
}
And that’s basically it. IOptionsSnapshot reloads the new setting when page is refreshed or when a new user requests page. I did not test this with IIS, and I am not sure if IIS automatically reloads(recycles) the application, similar to when we make changes to web.config. Anyway, I hope this helps. I will create a separate blog post about this with a complete downloadable project.
Hi dude,
Thanks for reply and sharing your good solution.
My fault was using EmbededResource, when a file changed to EmbededResource instead of Content, its combined to DLL and the file on server is not used.
Your solution and sample code are so useful.
Thanks
Really helpful strategy for separating the client configuration from the server (appsettings). FYI, I don’t know if it changed, but you would put the client file in the wwwroot and not the client root, but works like a charm. Thanks for the great tip
I’ve placed a feature flag in wwwroot/AppSettings.Development.json and I’m able to access the setting in my .razor.cs file no problem. However, when I publish the app (which consists of an Asp.Net API project and the Blazor WASM project) to Azure and add the same feature flag to settings -> configuration -> application settings for the app service, the deployed version of the app doesn’t seem to see this setting. I guess my question is, how are the server-side app config variables distinguished from the client-side variables once you deploy a Blazor WASM app to Azure? Hope this made sense.
Hi Luke, technically, a Blazor WASM app does not run on server, so by design any configuration that is set in Azure portal is not accessible to a WASM app.
From Microsoft: Azure App configuration provider isn’t appropriate for Blazor WebAssembly apps because Blazor WebAssembly apps don’t run on a server in Azure.
So, you can either keep using your appsettings.json for configurations that are not server specific. Or create an Azure function(a separate backend service) that returns Azure configurations to your WASM app using dependency injection(honestly, I have never done this before). You can read more about Azure Functions DI here – https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection.
I don’t think I have given you a good answer but I hope that helps a little.