2
votes

As described in this article: https://azure.microsoft.com/en-us/blog/windows-azure-web-sites-how-application-strings-and-connection-strings-work/, Azure Web Apps/Web Sites/Web Jobs can take their configuration settings (appSettings, connectionString) from environment variables instead of app.config/web.config.

For example, if an environment variable named "APPSETTING_appSettingKey" exists, it will override the following setting from app.config/web.config:

<appSettings>
  <add key="appSettingKey" value="defaultValue" /> 
</appSettings>

This works fine once the application is deployed in Azure, but I would like to use the same method when testing locally.

I tried to emulate this in a local command line:

> set APPSETTING_appSettingKey=overridedValue
> MyWebJob.exe

The web job accesses this setting using:

ConfigurationManager.AppSettings["appSettingKey"]

When running in Azure, it reads the value "overridedValue" as expected, but locally it reads the value "defaultValue" from the app.config file.

Should I expect this to work, or is this implemented only under an Azure environment?

I could obviously create an abstraction over ConfigurationManager that emulates this, but this wouldn't work when calling code that needs a connection string name instead of a connection string value. Also, I want to use the same method regardless of the environment to simplify management of settings.

There are 3 reasons why I need this:

1) I don't like the idea of deploying to production a web.config file that references connection strings, etc for a developement environment, because there's a risk of an error that would cause the development settings (in web.config) to be used in production (production web app connecting to development database, etc), for example if an environment variable is named incorrectly (after renaming the setting in web.config but forgetting to rename it in environment variables)

2) I'm trying to setup development environments where each developer has his own isolated cloud resources (storage account, databases,...). Currently, everyone has to manually edit his .config files to reference the correct resources, and be careful when checking-in or merging changes to these files.

3) A solution can have multiple projects that need to duplicate the same settings (main web app, web jobs, integration test projects,...). This causes a lot of work to ensure updated settings are replicated across all files.

This would be simplified if there was an environment-independent .config file without any actual configuration, each developer would configure a set of environment variables once and be able to use them for all parts of a solution.

3
You may give a try to CloudConfigurationManager ?Thomas
When running under Azure Web Sites/Web Jobs, ConfigurationManager will already implement behavior similar to CloudConfigurationManager. What I'm looking for is a way to have the same behavior locally (override web.config settings from environment variables, if present). I'll edit the question to explain why I need this.ckarras
@ckarras I think one of the problems you're is having is that when you define an app setting which is used locally, then that app setting (which could be a secret) is deployed to Azure, which as you stated you don't want. You might find it helpful to use web.config transformations to remove these values from the config file prior to deployment. For webjobs (or any project with an app.config) you'll need the SlowCheetah nuget package marketplace.visualstudio.com/….Howiecamp
Have you looked into using user secrets? For example, if you're using VIsual Studio, right click on your ASP.NET Core project and select "Manage User Secrets". This will bring up secrets.json. You can then stick local configuration values for your web app in there, and this file is blocked from check-in by default. One downside of this approach is that each developer would need to replicate the settings on their development machine, but otherwise it works quite well.ZenoArrow

3 Answers

3
votes

Yes, this special transformation of environment variables into config values is done via a component that is specific to Azure WebApps and won't be in play locally.

Generally people are fine with the local behavior this produces - locally you are reading from config settings as usual, but in Azure you're reading from secure settings that were configured via the App Settings portal blade (so these settings aren't in your source code).

You could write an abstraction over this if you wish, E.g. the WebJobs SDK actually does this internally (code here).

0
votes

When I am developing locally and want to consistantly use Environment.GetEnvironmentVariable. In my static class Main I have the following code:

if (config.IsDevelopment)
{
    config.UseDevelopmentSettings();
    Environment.SetEnvironmentVariable("UseDevelopmentSettings", "true");
}

Then in my static class Functions I add a static constructor and in there I call the static method below:

static void AddAppSettingsToEnvironmentVariables()
{
    String useDevelopmentSettings = Environment.GetEnvironmentVariable("UseDevelopmentSettings"); ;
    if (!(String.IsNullOrEmpty(useDevelopmentSettings)))
    {
        foreach (String key in ConfigurationManager.AppSettings.AllKeys)
        {
            Environment.SetEnvironmentVariable(key, ConfigurationManager.AppSettings[key]);
        }
    }
}

The code is small enough that I can simply comment it out before I test in Azure.

-1
votes

If you want to test the application with the value that will be used in Azure portal AppSettings/Connection String. I would recommend use HostingEnvironment.IsDevelopmentEnvironment. To ensure it will work, please change the <compilation debug="true" targetFramework="4.5.2" /> to <compilation debug="false" targetFramework="4.5.2" />. set the value with the same value in Azure portal if (HostingEnvironment.IsDevelopmentEnvironment == false). I have try with a simple project, hope it helps:

        public ActionResult Index()
        {
            if (HostingEnvironment.IsDevelopmentEnvironment == true)
            {
                ViewBag.Message = "Is development.";
            }
            else
            {
                ViewBag.Message = "Azure environment.";
            }
            return View();

        }

Here is the result:

enter image description here