25

I currentying trying to save the api url in an appsettings. However, the configuration.Propertiers seems to be empty. I am not sure how to get the setting. in program.cs:

public static async Task Main(string[] args)
{
   var builder = WebAssemblyHostBuilder.CreateDefault(args);
   //string url = builder.Configuration.Properties["APIURL"].ToString();
   foreach (var prop in builder.Configuration.Properties)
      Console.WriteLine($"{prop.Key} : {prop.Value}" );
   //builder.Services.AddSingleton<Service>(new Service(url));
   builder.RootComponents.Add<App>("app");
   await builder.Build().RunAsync();
}
Zo.
  • 260
  • 1
  • 3
  • 10
  • https://hutchcodes.net/2019/12/blazor-wasm-app-settings/ "There isn’t an easy way to just pass the settings into the client-side Blazor app, so we’ll need the app to request them from the server. We’ll create a ClientAppSettingsController to AppSettingsExample.Server to serve up these settings." – claudiom248 Mar 05 '20 at 20:33
  • Useful question: https://stackoverflow.com/questions/62731756/how-can-i-use-inject-a-service-in-a-normal-c-sharp-class-like-in-blazor-injec -- applied to the IConfiguration service – M.M Jan 05 '23 at 03:45

10 Answers10

21

Using ASP.NET Core 6.0 Blazor configuration. Blazor WebAssembly loads configuration from the following app settings files by default:

  • wwwroot/appsettings.json.
  • wwwroot/appsettings.{ENVIRONMENT}.json, where the {ENVIRONMENT} placeholder is the app's runtime environment.

Example:

wwwroot/appsettings.json

{
  "h1FontSize": "50px"
}

Pages/ConfigurationExample.razor

@page "/configuration-example"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example
</h1>

Warning Configuration and settings files in a Blazor WebAssembly app are visible to users. Don't store app secrets, credentials, or any other sensitive data in the configuration or files of a Blazor WebAssembly app.

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/configuration?view=aspnetcore-6.0

You can also bind the values to a class.

public class ClientAppSettings
{
    public string h1FontSize{ get; set; }
}

Then add this class as a Singleton in Program.cs:

var settings = new ClientAppSettings();
builder.Configuration.Bind(settings);
builder.Services.AddSingleton(settings);

Add namespace to _Imports.razor and then inject where needed to get settings with autocomplete in Visual Studio:

@inject ClientAppSettings ClientAppSettings
Ogglas
  • 62,132
  • 37
  • 328
  • 418
  • Your answer helped me out in a lousy Pluralsight course lab where I could not progress until I read your tip about the appsettings.json file automatically being picked up if resides in wwwroot. Thanks. – Tore Aurstad Jan 22 '22 at 20:53
  • Thank you, I used your Configuration.Bind to bind a group section from appSettings.json. I posted the answer below, yet you deserve all the credit! – JClarkCDS Jul 13 '23 at 04:22
18

Inkkiller nailed it. You can simplify the call into IConfiguration without the APIHelper class and access it directly in Program.cs from the WebAssemblyHostBuilder.

appsettings:

{
   "ServerlessBaseURI": "http://localhost:0000/",
}

Program.cs:

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);

    string serverlessBaseURI = builder.Configuration["ServerlessBaseURI"];
}


hubris
  • 181
  • 1
  • 3
17

This answer concerned blazor preview when blazor didn't support appsettings.json in wwwroot folder yet. You should use appsettings.json in wwroot folder now and WebAssemblyHostBuilder.Configuration. It also support per environment files (appsettings.{env}.Json).

I solve this issue by using a settings.json file store in the app wwwroot folder and register a task to get the settings :

Settings.cs

public class Settings
{
    public string ApiUrl { get; set; }
}

wwwroot/settings.json

{
   "ApiUrl": "https://localhost:51443/api"
}

Progam.cs

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);

    builder.Services.AddSingleton(async p =>
    {
        var httpClient = p.GetRequiredService<HttpClient>();
        return await httpClient.GetJsonAsync<Settings>("settings.json")
            .ConfigureAwait(false);
    });

SampleComponent.razor

@inject Task<Settings> getsettingsTask
@inject HttpClient client
...
@code {
    private async Task CallApi()
    {
        var settings = await getsettingsTask();
        var response = await client.GetJsonAsync<SomeResult>(settings.ApiUrl);
    }
}

This has advantages:

  • Doesn't share the server's appsettings.json file which can be a security hole
  • Configurable per environment
agua from mars
  • 16,428
  • 4
  • 61
  • 70
  • Thank you very much! I could get my head around it yesturday. – Zo. Mar 06 '20 at 15:24
  • 1
    As of .NET 5 it's actually called [`GetFromJsonAsync`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.json.httpclientjsonextensions.getfromjsonasync?view=net-7.0) – JBSnorro Dec 11 '22 at 18:25
10

You can also just (appsettings.json in wwwroot):

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("app");

        var url = builder.Configuration.GetValue<string>("ApiConfig:Url");
        builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(url) });
    }
}
Sunday
  • 631
  • 1
  • 7
  • 14
8

As of now, you can use the IConfiguration.

appsettings.json:

{
  "Services": {
    "apiURL": "https://localhost:11111/"
  }
}

.

using Microsoft.Extensions.Configuration;

public class APIHelper
    {
        private string apiURL;

        public APIHelper(IConfiguration config)
        {
            apiURL = config.GetSection("Services")["apiURL"];
            //Other Stuff
        }

    }
tbdrz
  • 1,811
  • 2
  • 12
  • 30
6

Blazor WASM appsettings.json

If you dont have appsettings.json in the wwwroot folder then simply:

  1. Right click on wwwroot folder.
  2. Click Add ==> New Item ==> App Settings File

This will add appsettings.json to your application. Open the appsettings.json file you will see a section in it already for database add a section like I have added apiinfo:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

  "apiinfo":{
    "apiurl": "your api url"
  }

}

Now when you want to call this section simply Inject configuration and call it like:

@inject Microsoft.Extensions.Configuration.IConfiguration config;

And to call the apiurl:

config.GetSection("apiinfo")["apiurl"].ToString()
zhulien
  • 5,145
  • 3
  • 22
  • 36
FarrukhMalik
  • 129
  • 1
  • 2
3

Also in .Net 5 & 6 you can set the value to Static Class.

Example:

wwwroot/appsettings.json

 "ServicesUrlOptions": {
   "Url": "https://domain.gr/services" }

Static Class

public static class ApplicationServicesSettings
{
    public const string ServicesUrl = "ServicesUrlOptions";
    public static ServicesUrlOptions ServicesUrlOptions { get; set; } = new ServicesUrlOptions();
}

public class ServicesUrlOptions
{
    public string Url { get; set; }
}

Finally bind the value at Program.cs

 builder.Configuration.GetSection(ApplicationServicesSettings.ServicesUrl).Bind(ApplicationServicesSettings.ServicesUrlOptions);

After in project you have access to key by

ApplicationServicesSettings.ServicesUrlOptions.Url
Baskovli
  • 530
  • 5
  • 13
2

as an example, I have it implemeneted like this (client-side Blazor):

appsettings.json:

{
    "api": "https://www.webapiurl.com/"
    "ForceHTTPS": false
}

then, have typed config class

 public class APISetting
    {

        public string api { get; set; }

        public bool ForceHTTPS { get; set; }

    }

then, load on startup:

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

        public APISetting GetConfiguration()
        {
            using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("appsettings.json"))
            using (var reader = new System.IO.StreamReader(stream))
            {
                return System.Text.Json.JsonSerializer.Deserialize<APISetting>(reader.ReadToEnd());
            }
        }
    }
yob
  • 528
  • 4
  • 9
0

create settings class:

public class Settings
{
    public string ApiUrl { get; set; }
}

create settings.json in wwwroot folder:

{
    "ApiUrl": "http://myapiurlhere"
}

and in .razor component read it like this:

@inject HttpClient Http
...
@code {
    private string WebApuUrl = "";

    protected override async Task OnInitializedAsync()
    {
        var response = await Http.GetFromJsonAsync<Settings>("settings.json");
        WebApuUrl = response.ApiUrl;
    }
}
Zviadi
  • 81
  • 1
  • 5
0

Building on @Ogglas answer. I changed the service Configuration.Bind to bind a section of an appSettings.json.

appSettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "myappSettings": {
    "Company": "ACME Sandbox",
    "ApiEndpoint": "https://api.sample.com:50443/",
    "ImageLocation": "\\\\OnPremise.sample.local\\Images",
    "ImageUrl": "https://cdn.somesite.com",
    "Emails": {
      "RequestTo": "team@degensrt.com",
      "SubmittedTo": "team@degensrt.com",
    }
  }
}

myappSettings.cs

public class myappSettings
{
    public string Company { get; set; }
    public string ApiEndpoint { get; set; }
    public string ImageLocation { get; set; }
    public string ImageUrl { get; set; }
    public appEmails Emails { get; set; }
}

public class appEmails
{
    public string RequestTo { get; set; }
    public string SubmittedTo { get; set; }
}

Then register and bind to the section myappSettings: in Program.cs:

//Application Settings
var settings = new myappSettings();
builder.Configuration.Bind("myappSettings", settings);
builder.Services.AddSingleton(settings);

Then inject and consume in your component:

@inject appSettings appSettings;
....
....
@code {
private string EmailTo = "";
    
protected override async Task OnInitializedAsync()
{
    EmailTo = appSettings.Emails.SubmittedTo;
}
}
JClarkCDS
  • 184
  • 2
  • 9