dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.15k stars 9.92k forks source link

Blazor WASM not loading appsettings.{environment}.json in Azure App Services #25152

Open hallidev opened 4 years ago

hallidev commented 4 years ago

Describe the bug

When developing locally (Blazor WASM), I have the following files in /wwwroot:

appsettings.json
appsettings.Development.json
appsettings.LocalDevelopment.json

My launchSettings.json specifies an ASPNETCORE_ENVIRONMENT of "LocalDevelopment".

When running locally, everything works as expected. appsettings.json and appsettings.LocalDevelopment.json are merged as expected.

I have just published the Blazor WASM app to Azure App Services, and appsettings.json merging fails. I have the ASPNETCORE_ENVIRONMENT set to "Development" in the App Service:

image

I have been able to confirm the failure by putting all of my settings in appsettings.json so that I don't need to rely on merging. The app runs as expected in the App Service.

To Reproduce

1: Create a new Blazor WASM ASP.NET Core Hosted application 2: Add appsettings.json, and appsettings.Development.json to /wwwroot 3: Add a configuration value to both files that requires merging. 4: Locally, set ASPNETCORE_ENVIRONMENT to "Development" 5: Confirm that the correct config value gets read 6: Deploy to Azure App Service 7: Set ASPNETCORE_ENVIRONMENT to "Development" for the App Service 8: BUG: Note that value is not read from appsettings.Development.json. It is read from appsettings.json.

Further technical details

.NET Core SDK (reflecting any global.json):
 Version:   3.1.401
 Commit:    5b6f5e5005

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19041
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.401\

Host (useful for support):
  Version: 3.1.7
  Commit:  fcfdef8d6b

.NET Core SDKs installed:
  2.1.700 [C:\Program Files\dotnet\sdk]
  2.1.701 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  2.2.300 [C:\Program Files\dotnet\sdk]
  2.2.301 [C:\Program Files\dotnet\sdk]
  2.2.401 [C:\Program Files\dotnet\sdk]
  3.0.100 [C:\Program Files\dotnet\sdk]
  3.1.101 [C:\Program Files\dotnet\sdk]
  3.1.401 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
mkArtakMSFT commented 4 years ago

Thanks for contacting us. This may be potentially related to another reported issue: https://github.com/dotnet/aspnetcore/issues/21992

ghost commented 4 years ago

Thanks for contacting us. We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost commented 3 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

hallidev commented 3 years ago

@mkArtakMSFT

I'm curious why this is considered minor severity and has been pushed from Next sprint planning? This is a pretty major issue and a deviation from how everything else in the .NET Core ecosystem works. It also makes managing configuration across environments very difficult. We have to manually edit appSettings.json to match the environment we're about to deploy to every single time we need to do a deployment.

I'm surprised that this issue hasn't been reported frequently. Am I missing something?

trygvelo commented 3 years ago

We solved it like this:

  1. In Visual Studio project properties -> "Build Event" -> "Pre-build event command line", add the following line: echo window.BlazorEnvironment = '$(ConfigurationName)'; > $(ProjectDir)wwwroot\js\BlazorEnvironment.js

  2. In index.html, BEFORE bootstrapping Blazor with this tag: , add the following to make sure the "blazor-environment" header is set to the correct value:

<script src="js/BlazorEnvironment.js"></script>
<script>
    const originalFetch = fetch;
    fetch = async (url, options) => {
        const response = await originalFetch(url, options);
        return url.endsWith('/blazor.boot.json')
            ? new Response(await response.blob(), { headers: { 'blazor-environment': window.BlazorEnvironment } })
            : response;
    };
</script>
hallidev commented 3 years ago

@trygvelo Thanks - will give this a try

safoster88 commented 3 years ago

I am also having this exact issue when hosting inside an nginx container.

I can see that the ASPNETCORE_ENVIRONMENT variable is set correctly, and that the files are present. However, only appsettings.json is ever loaded.

The script above will not work for my use-case, as I feed the variable through from an azure-pipeline script.

mathewjoe22 commented 3 years ago

This got resolved by using Pascal Case ASPNETCORE_ENVIRONMENT=Dev , ASPNETCORE_ENVIRONMENT=Production

StigHausberg commented 3 years ago

This got resolved by using Pascal Case ASPNETCORE_ENVIRONMENT=Dev , ASPNETCORE_ENVIRONMENT=Production

I'm not sure what you mean, we have the configuration in uppercase and it's not working,

StigHausberg commented 3 years ago

Any update on progress on this feature?

kiranu-dev commented 3 years ago

Any updates on this? Not sure how this could be treated as a minor issue!!! The entire development and debugging (via visual studio) works just fine and it blasts out on the very first deployment (I'm using docker with Nginx as the server).

While it is logical to think that "Environment Variable" does not make sense for a static website application, it is very sad that no proper warning is provided in the MSDN - https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/configuration?view=aspnetcore-5.0

From the source code, it is evident that app settings transformation will work ONLY for ASPNET hosted WASM apps, and for the rest of others, it will default to "Production":

image https://github.com/dotnet/aspnetcore/blob/6a929c3796f048d619bdd05969972d3a84669aac/src/Components/Web.JS/src/Platform/BootConfig.ts#L5


UPDATE - My Workaround


As I'm deploying the Blazor wasm in a Linux container (as Nginx as the server), I did the config "transform" during the build process. Updated docker file (pasting only relevant parts):

FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
..... deleting copy and restore lines for brevity...........
RUN dotnet publish "myblazorproj.csproj" -c Release -o /app/publish

# Use official nginx image as the base image
FROM nginx:latest as final
ARG BUILD_ENVIRONMENT
RUN echo $BUILD_ENVIRONMENT

COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/publish/wwwroot /usr/share/nginx/html
# This is to fix the bug mentioned here - https://github.com/dotnet/aspnetcore/issues/25152
# Everything works (appsettings transformation) during local debugging, but the environment is not getting picked properly on publish
# Fixing it by replacing the appsettings.json file with the env specific file
# NOTE - This is a blind file replace and hence appsettings transformation will not work; make sure all settings are present in the enc specifci files as well 
COPY --from=build /app/publish/wwwroot/appsettings.${BUILD_ENVIRONMENT}.json /usr/share/nginx/html/appsettings.json

EXPOSE 80

And during Docker build, pass the argument BUILD_ENVIRONMENT=

rileywhite commented 3 years ago

I'd love to see updates on this, as well. I see the "affected-very-few" label, but I feel like there is a fundamental and subtle issue with appsettings and non-dotnet blazorwasm hosts.

jweschenfelder commented 3 years ago

It seems it is not only an Azure problem, the same problem occurs on local machines as well. I followed the instructions told in https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-5.0 and then I do receive a HTTP 404 Not Found error message, Blazor WASM does not start at all. It seems it only works with one single or only in specific environments. The problem was also discussed here: https://github.com/dotnet/aspnetcore/issues/21992 - The answer was there that the problem will not be fixed in the near future by Microsoft. But in companies, multiple environments are often needed, e.g. if the same Blazor WASM shall e.g. run in two different production environments with different app settings. I would also love to have multiple environment support in Blazor WASM as soon as possible.

federicodibe commented 3 years ago

Same problem here, Microsoft wtf do you wanna fix that ?!

IvanJosipovic commented 3 years ago

Blazor WASM can't read the Environment variables. MS has two documented options here, https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/environments?view=aspnetcore-5.0 Either, set the env in JS on in the web.config by setting a http header that Blazor can read.

I'm using the web.config approach and have my ci/cd pipeline replace the environment on build.

Paul-Schroeder commented 3 years ago

Kudos to @trygvelo for such a creative answer, even if it only works for WebAssembly deployments from Visual Studio. It feels dirty and I can't say I like it, but it did work for me using .NET 5 with a few tweaks that I'll describe for others.

As mentioned, I added a Pre-build event, but with a minor directory change (removing '\js' from the directory path):

  1. In Visual Studio project properties -> "Build Event" -> "Pre-build event command line", add the following line: echo window.BlazorEnvironment = '$(ConfigurationName)'; > $(ProjectDir)wwwroot\BlazorEnvironment.js

  2. In index.html, BEFORE bootstrapping Blazor with this tag: , add the following to make sure the "blazor-environment" header is set to the correct value (again removing the '/js' directory from the path).

    <script src="BlazorEnvironment.js"></script>
    <script>
        const originalFetch = fetch;
        fetch = async (url, options) => {
            const response = await originalFetch(url, options);
            return url.endsWith('/blazor.boot.json')
                ? new Response(await response.blob(), { headers: { 'blazor-environment': window.BlazorEnvironment } })
                : response;
        };
    </script>
  1. Note that the '$(ConfigurationName)' usage in step 1 typically defaults to "Debug" or "Release" in standard project configurations. In order to ensure calls to HostEnvironment.IsDevelopment() and/or HostEnvironment.IsProduction() continue to function I created two new project configurations, 'Development' and 'Production'.

WebAssembly Project Configuration

If you do not do this, then all calls to the IsDevelopment() and IsProduction() methods will always return false. i.e.

    [Inject]
    public IWebAssemblyHostEnvironment env { get; set; }
...
    if (env.IsDevelopment())
    {
        // Do something in DEV that isn't done in PROD
    }
  1. Next, I renamed the 'child' appsettings.json files to 'appsettings.Development.json' and 'appsettings.Production.json', respectively to keep in sync with my renamed project configurations from step 3 as well as the $(ConfigurationName) variable from step 1. Note, I kept the original appsettings.json file to avoid 404 not found errors, but removed all content from it, except for some empty curly braces:
{ }

I did this because it seemed like the inheritance of values from appsettings.json to, say, appsettings.Production.json was not working correctly. In other words, when I had settings in both files, I believe I was getting the original configuration values from appsettings.json instead of the environment-specific ones. Transferring all DEV/Debug values from appsettings.json to the appsettings.Development.json file seemed to work best.

  1. Finally, I would advise that you create a test page to display configuration values once the code is deployed. Sometimes it seemed like changes were not taking effect for me until I did a hard refresh or specifically navigated to "/Index.html" (and then back to just "/"). Here is some sample code to get you started gathering/displaying configuration settings that may be of interest (in this case Identity Server 4 configuration values):
public string OidcConfigurationString
{
    get
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("OidcConfiguration: ");

        var oidcConfigSection = Configuration.GetSection("OidcConfiguration");
        var itemArray = oidcConfigSection.AsEnumerable();
        foreach (var item in itemArray)
        {
            sb.AppendLine($"{item.Key}: {item.Value}");
        }

        return sb.ToString();
    }
}

The output from this can simply be displayed in a razor page as such:

<div style="margin-left:15px;">
    @((MarkupString)OidcConfigurationString)
</div>

As you can guess, this was a big, frustrating, time sink and I have a hard time believing there isn't a better way. But, until I am enlightened by that better way, this will get me (and hopefully you) past the issue.

Kurti123 commented 2 years ago

It's not only a problem of WASM and Azure. I've been running into the same bug on my local Blazor server app with IISExpress. Everything worked fine when I had set ASPNETCORE_ENVIRONMENT=Development but as soon as i switched to Production, I got this 404 error.

knight1219 commented 2 years ago

I reported this back in reported this in May of 2020 #21992 and it is still a lingering issues in .net Core 3.1, .net 5 and potentially .net 6? We are now a year and a half removed and this is still not fixed. Unless you have 2 environment, it is unthinkable that this could be an acceptable state.

Incase anyone would like to know, I was able to work around it by adding a second environment variable enviro and set that to my sites environment (dev, qa, uat, prod, etc.). I read that variable out like I would ASPNETCORE_ENVIRONMENT and created a middleware that sets the blazor-environment header with this value. This allows hosted WASM sites to properly pull in the environment from inside Blazor and things work as they should. It also allows me to pull in the proper appsettings.*.json files on the server.

I hope that one day this gets solved by the framework.

fcxxzux commented 2 years ago

Encountered the same issue with dotnet 6.0.100 After setting "ASPNETCORE_ENVIRONMENT": "Production" or anything other than Development, Blazor WASM failed to serve, like what mentioned in #21992

It's very annoying as I want to change LogLevel between my dev machine and production machine by just setting launch profile (not changing appsettings.json files) as doc suggested Use multiple environments in ASP.NET Core , especially after several frustrating days.


Or I'd like to propose that we can have some note in the docs mentioned above that

For Blazor WASM project, Do NOT change ASPNETCORE_ENVIRONMENT to anything other than Development, this won't work

AlexBrunnerACAG commented 2 years ago

I reported this back in reported this in May of 2020 #21992 and it is still a lingering issues in .net Core 3.1, .net 5 and potentially .net 6? We are now a year and a half removed and this is still not fixed. Unless you have 2 environment, it is unthinkable that this could be an acceptable state.

Incase anyone would like to know, I was able to work around it by adding a second environment variable enviro and set that to my sites environment (dev, qa, uat, prod, etc.). I read that variable out like I would ASPNETCORE_ENVIRONMENT and created a middleware that sets the blazor-environment header with this value. This allows hosted WASM sites to properly pull in the environment from inside Blazor and things work as they should. It also allows me to pull in the proper appsettings.*.json files on the server.

I hope that one day this gets solved by the framework.

Hi Knight1219 you mentioned a middleware, you implemented by yourself. Do you think that getting this middleware could be possible? Maybe we could find an arrangement? I would like to setup a proper staging/production environment and I am stuck at this topic as well.

ToddEvansHome commented 2 years ago

I am having this same issue using .NET 6.0.2. I have confirmed that blazor.boot.json Response Header does not have "blazor-environment" set

Questions from similar bug: Could you check the following things?

appsettings.{environment}.json file are being published Server process is setting the ASPNETCORE_ENVIRONMENT variable blazor.boot.json does not have the response header (Blazor-Environment) appSettings.json is requested by the browser instead of appsettings.{environment}.json file

Please escalate this bug.

Note: I am not sure why this bug has a label of "affected-very-few" or "severity-minor".

nheath99 commented 2 years ago

"affected-very-few", "severity-minor", ".NET 7 planning" - utterly ridiculous. This is such a fundamental aspect of app configuration and there is no stable workaround. Thanks a bunch Microsoft.

knight1219 commented 2 years ago

For ASP.NET Core Hosted Blazor WASM, This is the middleware I created. The enviro variable is an additional environment variable I use to set dev/qa/prod. This should be the first middleware you register.

    public class BlazorEnviromentMiddleware
    {
        private readonly RequestDelegate next;
        private readonly IConfiguration configuration;

        public BlazorEnviromentMiddleware(RequestDelegate next, IConfiguration configuration)
        {
            this.next = next;
            this.configuration = configuration;
        }

        public async Task Invoke(HttpContext context)
        {
            // Call the next delegate/middleware in the pipeline
            context.Response.OnStarting(async o => {
                if (o is HttpContext ctx)
                {
                    if(ctx.Response.Headers.ContainsKey("blazor-environment"))
                    {
                        ctx.Response.Headers.Remove("blazor-environment");
                    }

                    ctx.Response.Headers.Add("blazor-environment", this.configuration.GetValue<string>("enviro"));
                }

                await Task.CompletedTask;
            }, context);
            await this.next(context);
        }
    }
gilm0079 commented 2 years ago

@knight1219 your middleware worked for me as well to fix the same issue I was having. My hosted blazor wasm app was published to IIS. The server had the aspnetcore environment variable correctly, but it wasn't being passed down to the client wasm app.

I ended up going a slightly different direction though. Correct me if I'm wrong, but the middleware is appending the response header to all responses? I instead let the UseStaticFiles AppBuilder extension append the blazor-environment header to the response serving the blazor.boot.json file only. I was already doing another response header modification to fix another blazor wasm problem with integrity here: https://github.com/dotnet/aspnetcore/issues/38552

Here is what I went with that combined the environment variable with the caching issue.

app.UseStaticFiles(new StaticFileOptions {
    OnPrepareResponse = context => {
        if (context.File.Name == "service-worker-assets.js") {
            context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
            context.Context.Response.Headers.Add("Expires", "-1");
        }

        if (context.File.Name == "blazor.boot.json") {
            if (context.Context.Response.Headers.ContainsKey("blazor-environment")) {
                context.Context.Response.Headers.Remove("blazor-environment");
            }

            context.Context.Response.Headers.Add("blazor-environment", env.EnvironmentName);
        }
    }
  });
CameronVetter commented 2 years ago

"affected-very-few", "severity-minor", ".NET 7 planning" - utterly ridiculous. This is such a fundamental aspect of app configuration and there is no stable workaround. Thanks a bunch Microsoft.

Agreed, I don't understand how this is minor and very few affected. This makes Blazor WASM unusable in a production environment. Can someone from the team explain how this is a minor issue? What is the recommended method for deploying into multiple environments with the same code?

Here is the very hacky workaround that we ended up with in the index.html file we replaced:

<script src="_framework/blazor.webassembly.js"></script>

with:

    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
        if (window.location.hostname.includes("localhost") || window.location.hostname.includes("dev")) {
            Blazor.start({
                environment: "Development"
            });
        }
        else if (window.location.hostname.includes("demo")) {
            Blazor.start({
                environment: "Demo"
            });
        }
        else if (window.location.hostname.includes("stage")) {
            Blazor.start({
                environment: "Staging"
            });
        }
        else {
            Blazor.start({
                environment: "Production"
            });
        }
    </script>
AlexBrunnerACAG commented 2 years ago

We switched the standalone WASM application to hosted WASM application and followed the environment approach described in https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/environments?view=aspnetcore-6.0#set-the-environment-for-azure-app-service.

Djeffl commented 2 years ago

Same issue. Thought we were missing something, but as it seems it's impossible to resolve, unless you only want to use this during the production environment while deploying.

I'm trying to fix it via my deploy pipeline where I modify the name of the appsettings.{environment} to production.

jbenzing commented 2 years ago

Same issue here. @CameronVetter 's work-around is working for us, Thank you for sharing it.

I did have to make sure it was authentication line below: <script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>

knight1219 commented 2 years ago

I like @gilm0079 use of the UseStaticFiles middleware. I might even modify my code to do that to help not expose that in every API call i make to my backend. I'm not fond of using a URL or hostname to try and figure out what environment is being used (qa/staging/test are all urls used in my environments for the same stage of deployment).

I did see this was added to the .NET 7 preview milestone last month, is there active work being done on this issue? It's been a outstanding issue since Blazor's launch (not sure why my issue was closed #21992 about this.) I would love to tell my Architecture team we don't need an extra environment variable and we can go back to using ASPNETCORE_ENVIRONMENT.

It still is a bit hard to understand how this isn't an issue for more people and how the Blazor team doesn't see this as a critical issue.

ghost commented 2 years ago

Thanks for contacting us. We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

CameronVetter commented 2 years ago

Can someone on the team please comment? I'm baffled how Blazor WASM is considered even production worthy with this very basic feature broken. Seeing this issue keep getting kicked down the road makes me feel like we are all missing something. What is the official stance on what we are supposed to do to make Blazor suitable for multi-environment deployments? The documentation implies what this thread is labeling as a bug should work, yet the bot is telling us this is not a bug and the team appears disinterested.

gilm0079 commented 2 years ago

@CameronVetter I'm just a user of Blazor like you. It seems like a lot of things, not just Blazor, are pushed to the .NET7 milestone. I have several shims in Blazor for the time being until .NET 7 is GA. I've just been working around it in the meantime.

My post above seems to be working great without needing to set the environment via javascript. Blazor reads the "blazor-environment" http header when loading blazor.boot.json. I'd recommend going that route for the time being as the static files response shim takes care of the 1 piece in the recommended pathway that is not currently working which is the blazor hosted environment should be setting the header value without manual intervention.

CameronVetter commented 2 years ago

@CameronVetter I'm just a user of Blazor like you. It seems like a lot of things, not just Blazor, are pushed to the .NET7 milestone. I have several shims in Blazor for the time being until .NET 7 is GA. I've just been working around it in the meantime.

My post above seems to be working great without needing to set the environment via javascript. Blazor reads the "blazor-environment" http header when loading blazor.boot.json. I'd recommend going that route for the time being as the static files response shim takes care of the 1 piece in the recommended pathway that is not currently working which is the blazor hosted environment should be setting the header value without manual intervention.

There are numerous hacky workarounds in this thread that work. My question was for someone from Microsoft on this team that is deciding not to fix this to give us an answer on what the approach should be since what is documented doesn't work.

DuckScapePhilip commented 2 years ago

Why is this not fixed? The issue was reported 2 years ago.

ball dropped

tchelidze commented 2 years ago

Environment header in blazor.boot.json response looks Good. Console write builder.HostEnvironment.Environment shows the proper environment. but still, the appropriate appsettings json is not fetched from server

image image image image

Looking at the source code

image

WebAssemblyHostEnvironment.Environmet is set to dev (as shown in console log). if that is the case, then why isn't apssettings.dev.json is pulled from server

tchelidze commented 2 years ago

Looking at Blazor._internals.getConfig function, turns out, Blazor._internals.getConfig function only pulls appsetting file If it is listed in blazor.boot.json file.

Looking at blazor.boot.json, files were listed in pascal case, so appsettings.Dev.json, so i set the ASPNETCORE_ENVIRONMENT env var to Dev instead of dev.

image

hypdeb commented 2 years ago

I'm guessing this is also affecting explicit calls to AddJsonFile the same way right ?

tchelidze commented 2 years ago

I'm guessing this is also affecting explicit calls to AddJsonFile the same way right ?

I dont think there is a way to add json file manually in blazor. appsettings.json and appsettings.env.json seems pretty hard coded

knight1219 commented 2 years ago

You can still use this:

var env = "dev";
var builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
builder.AddJsonFile($"appsettings.{env}.json");

You just need to set env from somewhere. I guess it depends on how you are hosting your app.

hypdeb commented 2 years ago

It doesn't seem to work, I get a FileNotFound. I have verified that the file is in the wwwroot folder. It seems to expect a physical path and doesn't try to fetch it using a relative path.

tchelidze commented 2 years ago

Jeep in mind that that executes on FE and configuration builder alone is not going to pull those files from BE

PelleRavn commented 2 years ago

I used the information from @tchelidze, and changed my filename to appsettings.Dev.json, and then changed my ASPNETCORE_ENVIRONMENT to Dev, then it started working correctly.

This seems very odd, and not at all aligned with how other .NET environments does it - so I totally agree with the other conclusions: This shouldn't be a minor issue.

ghost commented 1 year ago

Thanks for contacting us. We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

sturlath commented 1 year ago

Just to add how I´m doing this in case it helps someone down the line. It's probably not the best solution but I made it work for me.

I have a Release (this one is for my dev environment, and then I have another one for production that is 99% the same but with different variables)

image

where I do a JSON variable substitution on appsettings.Production.json (since that is always uesed)

image

so when there is a release the variables I have added are swapped out

image

Best would be if these things could be included in the project somehow and picked up from the AppService based on env or config. Little strange that this has been moved all the way to .NET 8 I have to say...

kingua commented 1 year ago

@sturlath, are you not serving the .gz or .br versions of the appsettings.env.json file or are you updating those as well?

jasonshave commented 1 year ago

Adding the appsettings.Development.json (with an upper-case "D") to the \wwwroot folder fixed this for me.

Creastoff commented 1 year ago

Our use case for this was to avoid tokenisation during deployment as that would fail integrity checks. We realised that WASM application can't read from Azure App Service app settings because its client side (probably why it got pushed for fixing, it is not very straight forward)

Its a shame that Azure App Service can't push that setting into the web.config httpProtocol.customHeaders section as the Blazor-Environment header automatically, though I don't think that wouldn't work for all scenarios anyway (another reason for the complexity)

Eventually we programmatically modified the web.config in a published artifact so that it would return the appropriate environment's header after deployment meaning we could add a file named like 'appsettings.qua.json' to our wwwroot folder.

DISCLAIMER: because all environments appsettings files need to be in wwwroot for this to work, this means the end user can access all files if they know the path. Naturally, you shouldn't be storing secrets here anyway because its client side - but you may also not want to do this if you don't want to expose your internal environment settings.

$environment = "qua"
$zipName = "drop"

#Extract the contents of archive for modification
Expand-Archive -Path "$zipName.zip" -Force
#Get existing XML file
[xml]$xml = Get-Content "$zipName\web.config"
$referenceNodeForInsertionPosition = $xml.configuration.'system.webServer'.staticContent

#Insert required node into XML at a specific position
$newNode = [xml]@"
<httpProtocol>
      <customHeaders>
        <add name="Blazor-Environment" value="$environment"/>
      </customHeaders>
    </httpProtocol>
"@
$newNode = $xml.ImportNode($newNode.httpProtocol, $true)
$xml.configuration.'system.webServer'.InsertBefore($newNode, $referenceNodeForInsertionPosition) | out-null

#Overwrite original XML
$path = Get-Location
$xml.Save($path.Path + "\$zipName\web.config")

#Archive folder and overwrite original zip
Compress-Archive -Path ($path.Path + "\$zipName\*") -DestinationPath "$zipName.zip" -CompressionLevel Optimal -Force
ghost commented 11 months ago

To learn more about what this message means, what to expect next, and how this issue will be handled you can read our Triage Process document. We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. Because it's not immediately obvious what is causing this behavior, we would like to keep this around to collect more feedback, which can later help us determine how to handle this. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact work.

CameronVetter commented 11 months ago

The issue has been figured out and is an issue with case sensitivity. Saying its "not immediately obvious" is not a correct assessment. Please see @jasonshave comment above... This should be fixed ASAP, this has a huge impact and is a minor fix @mkArtakMSFT

TBG-FR commented 9 months ago

It also looks like (maybe it's an intended behaviour, you'll tell me) Blazor WASM uses only appsettings.{...}.files that are present at buildtime. If my environment is Staging and I add a appsettings.Staging.json file at runtime (using a docker-compose volume instruction, for example), it doesn't use or see it, and blazor.boot.json only displays files that were present at buildtime appsettings: [appsettings.example.json", "../appsettings.json"]... You would expect it to take them dynamically (as it does by taking into account appsettings.json modifications at runtime)

Maybe that's related to Azure's issue, just dropping that information here