GregH
GregH

Reputation: 5459

Blazor: Managing Environment Specific Variables

How can I manage access variables which differ among environments in client side blazor? Normally since I use Azure to publish applications, I'd use the appsettings.json file for local app settings and then set up entries in the Azure Application Settings section of my App Service for entries that differ between local environments and other environments.

An example of what I'm looking to accomplish:

Client side Blazor:

@functions {
    //...more code here
    await Http.PostJsonAsync<object>("http://localhost:50466/api/auth/register", vm);
}

on the deployed web server this should be transformed to:

@functions {
    //...more code here
    await Http.PostJsonAsync<object>("http://wwww.mywebsite.com/api/auth/register", vm);
}

So I'm looking for a way to store the site root url in an environment variable and transform it upon publish. Is there a Blazor-ey way to do this?

Upvotes: 15

Views: 17249

Answers (7)

ionrazvan
ionrazvan

Reputation: 181

In Net Core 3.1 and Net 5 you can just create in the wwwroot the additional files for your environments: I have wwwroot/appsettings.json; and then also in the wwwroot the appsettings.Development.json and appsettings.Production.json. Make sure you mark them as Copy if newer in the Properties section. They should be picked up automatically by the build.

Upvotes: 0

user12228709
user12228709

Reputation:

I use Environment variables for all my Blazor sites:

This class EnvironmentVariableHelper is part of Nuget package DataJuggler.UltimateHelper.Core

using System;
using System.Collections.Generic;
using System.Text;

namespace DataJuggler.UltimateHelper.Core
{
    public class EnvironmentVariableHelper
    {

        #region Methods

            #region GetEnvironmentVariableValue(string variableName)
            /// <summary>
            /// This method is used to get an environment value
            /// </summary>
            /// <param name="variableName"></param>
            /// <returns></returns>
            public static string GetEnvironmentVariableValue(string variableName)
            {
                // initial value
                string value = "";

                try
                {
                    if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                    {
                        // Change the directory to %WINDIR%
                        value = Environment.GetEnvironmentVariable(variableName, EnvironmentVariableTarget.Machine);
                    }
                }
                catch (Exception error)
                {
                    // for debugging only, do something else with it if you need to
                    DebugHelper.WriteDebugError("GetEnvironmentVariableValue", "GetEnvironmentVariableValue", error);
                }

                // return value
                return value;
            }
            #endregion

        #endregion

    }
}

To create an Environment Variable, in Windows 10 Search Box start typing:

Edit System Environment Variables

enter image description here

Then make sure to add your variable to the System Environment Variables at the bottom (not the top section, as that is only for your user account and it won't work).

enter image description here

Then enter a variable name and a value and hit 'OK'.

enter image description here

Then to use it:

string value = EnvironmentVariableHelper.GetEnvironmentVariableValue("Variable Name");

Upvotes: 0

Morten_564834
Morten_564834

Reputation: 1667

appsettings are now supported in blazor directly so you can inject it: https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-3-release-now-available/

Upvotes: 4

i31nGo
i31nGo

Reputation: 1502

My solution was creating the 3 corresponding files in the root project solution

  • appsettings.json
  • appsettings.Debug.json
  • appsettings.Release.json

then in pre-build event of your project replace the correct file to wwwroot directory

if $(ConfigurationName) == Debug (
copy /Y "$(ProjectDir)appsettings.Debug.json" "$(TargetDir)..\..\..\wwwroot\appsettings.json"

) ELSE (
copy /Y "$(ProjectDir)appsettings.Release.json" "$(TargetDir)..\..\..\wwwroot\appsettings.json" )

Upvotes: 1

civan
civan

Reputation: 263

In addition to the answer from @Kliment Ru, there is also this possibility where you can use the configuration file directly in the page and you don't have to implement a separate DTO as a variable holder:

appsettings.json (you can use SlowCheetah to create debug and release files and override the parameters):

{
    "Host": "bla"
}

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(GetConfiguration());
    }

    public void Configure(IComponentsApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }

    private IConfiguration GetConfiguration()
    {
        using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("appsettings.json");
        return new ConfigurationBuilder()
            .AddJsonStream(stream) // key method to use, reads JSON stream
            .Build(); // builds the configuration from embedded stream
    }
}

and in razor page you have:

@page "/Task/list"
@inject HttpClient http
@inject Microsoft.Extensions.Configuration.IConfiguration configuration

...some HTML code

@code {
    private IEnumerable<Model.StoreTask> storeTasks;

    protected override async Task OnInitializedAsync()
    {
        storeTasks = await http.GetJsonAsync<IEnumerable<Model.StoreTask>>(configuration["Host"] + "GetStoreTasks"); // you can use the configuration directly (bla/GetStoreTasks)
    }
}

Upvotes: 0

Kliment Ru
Kliment Ru

Reputation: 2137

You can create singleton with configuration interface and inject it in you components.

.csproj

<ItemGroup>
   <EmbeddedResource Include="appsettings.Development.json" Condition="'$(Configuration)' == 'Debug'">
     <LogicalName>appsettings.json</LogicalName>
   </EmbeddedResource>
   <EmbeddedResource Include="appsettings.json" Condition="'$(Configuration)' == 'Release'">
      <LogicalName>appsettings.json</LogicalName>
   </EmbeddedResource>
</ItemGroup>

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(GetConfiguration());
    }

    private IConfiguration GetConfiguration()
    {
        // Get the configuration from embedded dll.
        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("appsettings.json"))
        using (var reader = new StreamReader(stream))
        {
            return JsonConvert.DeserializeObject<IConfiguration>(reader.ReadToEnd());
        }
    }

MyComponent.razor

@inject Configuration.IConfiguration Configuration;

Or look this issue

Upvotes: 5

Vibeeshan Mahadeva
Vibeeshan Mahadeva

Reputation: 7248

There are multiple ways use can do this,

I believe there is no any official method documented yet!

My recommendation is to use the good old method, using multiple config files for different environments and copying only the config files to be used in the intended environemnt.

Create a folder called env in the solution folder. and create sub folders called dev and prod. like below.

|- env
   |- dev
   |- prod
   |

Place your different config files (file with same name and different configs) inside dev and prod folders.

Create a batch file to copy appropreate environment to wwwroot folder. (I prefer this than the next step since, this is much CI friendly , no need to install Visual Studio in build server)

OR

add the below code to the post-build event of the Blazor Project

if $(ConfigurationName) == Debug (
  copy /Y "$(ProjectDir)env\dev\*" "$(TargetDir)\wwwroot"
) ELSE (
  copy /Y "$(ProjectDir)env\prod\*" "$(TargetDir)\wwwroot"
)

Since your config file is in the www folder you can easily refer this from the blazor app by opening the file and reading whats inside this.

Upvotes: 3

Related Questions