ChatGPT解决这个技术问题 Extra ChatGPT

Publish to IIS, setting Environment Variable

Reading these two questions/answers I was able to run an Asp.net 5 app on IIS 8.5 server.

Asp.net vNext early beta publish to IIS in windows server

How to configure an MVC6 app to work on IIS?

The problem is that the web app is still using env.EnvironmentName with value Development even when run on IIS.

Also, I want to run two versions of the same Web (Staging, Production) on the same server, so I need a method to set the variable for each Web separately.

How to do this?

One have typically three network environments Development, Staging and Production. The web server is in one the environment. Thus setting of system environment variable for the server is not a real restriction typically. One can still use Properties\launchSettings.json to simulate another environment for debugging in Visual Studio.

J
Johnny Wu

This answer was originally written for ASP.NET Core RC1. In RC2 ASP.NET Core moved from generic httpPlafrom handler to aspnetCore specific one. Note that step 3 depends on what version of ASP.NET Core you are using.

Turns out environment variables for ASP.NET Core projects can be set without having to set environment variables for user or having to create multiple commands entries.

Go to your application in IIS and choose Configuration Editor. Select Configuration Editor Choose system.webServer/aspNetCore (RC2 and RTM) or system.webServer/httpPlatform (RC1) in Section combobox Choose Applicationhost.config ... in From combobox. Right click on enviromentVariables element, select 'environmentVariables' element, then Edit Items. Set your environment variables. Close the window and click Apply. Done

This way you do not have to create special users for your pool or create extra commands entries in project.json. Also, adding special commands for each environment breaks "build once, deploy many times" as you will have to call dnu publish separately for each environment, instead of publish once and deploying resulting artifact many times.

Updated for RC2 and RTM, thanks to Mark G and tredder.


For step 3 I used system.webServer/aspNetCore instead.
Won't the settings added via the Configuration Editor get wiped out on the next deployment?
@brad-gardner if changes are made to Applicationhost.config instead of web.config, then changes will be persisted between deployments.
@the-red-pea note that in instructions you linked, web.config is changed, not applicationhost.config. Any changes to web.config on specific IIS server will be lost on next deployment. Changes to applicationhost.config are persisted on specific IIS server between deployments.
Works for Asp.Net Core 2.0
T
Trevor Daniels

Update web.config with an section under

<configuration>
  <system.webServer>
    <aspNetCore .....>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

Or to avoid losing this setting when overwriting web.config, make similar changes to applicationHost.config specifying the site location as @NickAb suggests.

<location path="staging.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>
<location path="production.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>

This is different in a way that your web.config is a part of project and is versioned in VCS. If you have multiple environments, like prod, staging, dev, then you will need some way to transform web.config for each one. Changing ApplicationHost.config in IIS affects this IIS only. So that you can have single web.config in your VCS and environment variables specific to IIS that override web.config variables. ApplicationHost.config can be edited programatically using PowerShell iis.net/learn/manage/powershell/…
Thanks @NickAb, that avoids having to update web.config every deploy. I've updated my answer.
I'm having trouble with doing this from powershell I keep getting Target configuration object '/system.webServer/aspNetCore/environmentVariables/environmentVariable is not found ... Normally to set some variable I would write something like this: Set-WebConfigurationProperty -PSPath IIS:\ -location example.com -filter /system.webServer/aspNetCore/environmentVariables/environmentVariable -name ASPNETCORE_ENVIRONMENT -value Staging what Im I missing?
I went back to what I knew and used appcmd instead.
@Christian, check out this answer: stackoverflow.com/a/50869935/33533 The environment variable name and value go in a hash table, so from your example it would be Set-WebConfigurationProperty -PSPath IIS:\ -Location example.com -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = 'Staging' }
S
Stephen Rauch

You could alternatively pass in the desired ASPNETCORE_ENVIRONMENT into the dotnet publish command as an argument using:

/p:EnvironmentName=Staging

e.g.:

dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging

This will generate out the web.config with the correct environment specified for your project:

<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>

C
CodeNotFound

Edit: as of RC2 and RTM releases, this advice is out of date. The best way I have found to accomplish this in release is to edit the following web.config sections in IIS for each environment:

system.webServer/aspNetCore:

Edit the environmentVariable entry and add an environment variable setting:

ASPNETCORE_ENVIRONMENT : < Your environment name >

As an alternative to drpdrp's approach, you can do the following:

In your project.json, add commands that pass the ASPNET_ENV variable directly to Kestrel: "commands": { "Development": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Development", "Staging": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Staging", "Production": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Production" }

When publishing, use the --iis-command option to specify an environment: dnu publish --configuration Debug --iis-command Staging --out "outputdir" --runtime dnx-clr-win-x86-1.0.0-rc1-update1

I found this approach to be less intrusive than creating extra IIS users.


If you are publishing through visual studio's msdeploy. Then you can put Staging in your .pubxml file and it will deploy using the specified IIS command even though you cant specify it in the publish UI.
@DeanNorth - This is golden!! Works like a champ! Thanks for sharing!
A
Abhinav Galodha

Other than the options mentioned above, there are a couple of other Solutions which works well with automated deployments or require fewer configuration changes.

1. Modifying the project file (.CsProj) file

MSBuild supports the EnvironmentName Property which can help to set the right environment variable as per the Environment you wish to Deploy. The environment name would be added in the web.config during the Publish phase.

Simply open the project file (*.csProj) and add the following XML.

<!-- Custom Property Group added to add the Environment name during publish
  The EnvironmentName property is used during the publish for the Environment variable in web.config
  -->
  <PropertyGroup Condition=" '$(Configuration)' == '' Or '$(Configuration)' == 'Debug'">
    <EnvironmentName>Development</EnvironmentName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' != '' AND '$(Configuration)' != 'Debug' ">
    <EnvironmentName>Production</EnvironmentName>
  </PropertyGroup>

Above code would add the environment name as Development for Debug configuration or if no configuration is specified. For any other Configuration the Environment name would be Production in the generated web.config file. More details here

2. Adding the EnvironmentName Property in the publish profiles.

We can add the <EnvironmentName> property in the publish profile as well. Open the publish profile file which is located at the Properties/PublishProfiles/{profilename.pubxml} This will set the Environment name in web.config when the project is published. More Details here

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

3. Command line options using dotnet publish

Additionaly, we can pass the property EnvironmentName as a command line option to the dotnet publish command. Following command would include the environment variable as Development in the web.config file.

dotnet publish -c Debug -r win-x64 /p:EnvironmentName=Development


This doest appear to work in .net core 3.1 its still not set for me.
@rouge39nin - I tested it and it worked in .net core 3.1. Can you please provide more details on what you tried and what is your hosting method?
C
Christian Del Bianco

I have my web applications (PRODUCTION, STAGING, TEST) hosted on IIS web server. So it was not possible to rely on ASPNETCORE_ENVIRONMENT operative's system enviroment variable, because setting it to a specific value (for example STAGING) has effect on others applications.

As work-around, I defined a custom file (envsettings.json) within my visualstudio solution:

https://i.stack.imgur.com/RdNfP.png

with following content:

{
  // Possible string values reported below. When empty it use ENV variable value or Visual Studio setting.
  // - Production
  // - Staging
  // - Test
  // - Development
  "ASPNETCORE_ENVIRONMENT": ""
}

Then, based on my application type (Production, Staging or Test) I set this file accordly: supposing I am deploying TEST application, i will have:

"ASPNETCORE_ENVIRONMENT": "Test"

After that, in Program.cs file just retrieve this value and then set the webHostBuilder's enviroment:

    public class Program
    {
        public static void Main(string[] args)
        {
            var currentDirectoryPath = Directory.GetCurrentDirectory();
            var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
            var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
            var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();

            var webHostBuilder = new WebHostBuilder()
                .UseKestrel()
                .CaptureStartupErrors(true)
                .UseSetting("detailedErrors", "true")
                .UseContentRoot(currentDirectoryPath)
                .UseIISIntegration()
                .UseStartup<Startup>();

            // If none is set it use Operative System hosting enviroment
            if (!string.IsNullOrWhiteSpace(enviromentValue)) 
            { 
                webHostBuilder.UseEnvironment(enviromentValue);
            }

            var host = webHostBuilder.Build();

            host.Run();
        }
    }

Remember to include the envsettings.json in the publishOptions (project.json):

  "publishOptions":
  {
    "include":
    [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "envsettings.json",
      "appsettings.json",
      "appsettings*.json",
      "web.config"
    ]
  },

This solution make me free to have ASP.NET CORE application hosted on same IIS, independently from envoroment variable value.


Very nice, the only change I suggest is swap var currentDirectoryPath = Directory.GetCurrentDirectory(); for var currentDirectoryPath = PlatformServices.Default.Application.ApplicationBasePath; This is much safer way to get the current dir.
What a great out of the box experience, when you have to create another layer of configs to manage configs of a framework
The assertion that "So it was not possible to rely on ASPNETCORE_ENVIRONMENT operative's system enviroment variable," might not be correct. Each application has it's own pool so there is nothing stopping you from setting the environment per app.
c
cvbarros

After extensive googling I found a working solution, which consists of two steps.

The first step is to set system wide environment variable ASPNET_ENV to Production and Restart the Windows Server. After this, all web apps are getting the value 'Production' as EnvironmentName.

The second step (to enable value 'Staging' for staging web) was rather more difficult to get to work correctly, but here it is:

Create new windows user, for example StagingPool on the server. For this user, create new user variable ASPNETCORE_ENVIRONMENT with value 'Staging' (you can do it by logging in as this user or through regedit) Back as admin in IIS manager, find the Application Pool under which the Staging web is running and in Advanced Settings set Identity to user StagingPool. Also set Load User Profile to true, so the environment variables are loaded. <- very important! Ensure the StagingPool has access rights to the web folder and Stop and Start the Application Pool.

Now the Staging web should have the EnvironmentName set to 'Staging'.

Update: In Windows 7+ there is a command that can set environment variables from CMD prompt also for a specified user. This outputs help plus samples:

>setx /?

It appears that in ASP.NET 5 RC1, the environment variable was changed to Hosting:Environment.
How do we set "Load User Profile" to true when we deploy this to Azure Web App?
@PunitGanshani As I understand, there is a "application settings" section in azure portal for web app where you can set environment key/value pairs: azure.microsoft.com/en-us/documentation/articles/…
@GradyWerner For RC2 they're changing it (as of now) to ASPNET_ENVIRONMENT ;-)
@b.pell It appears it's now ASPNETCORE_ENVIRONMENT :)
M
MarredCheese

Just add to your publish profile:

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

That information gets copied to web.config. (Don't set web.config manually since it gets overwritten.)

Source: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments


d
dasch88

Similar to other answers, I wanted to ensure my ASP.NET Core 2.1 environment setting persisted across deployments, but also only applied to the specific site.

According to Microsoft's documentation, it is possible to set the environment variable on the app pool using the following PowerShell command in IIS 10:

$appPoolName = "AppPool"
$envName = "Development"
cd "$env:SystemRoot\system32\inetsrv"
.\appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$appPoolName'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='$envName']" /commit:apphost

I unfortunately still have to use IIS 8.5 and thought I was out of luck. However, it is still possible to run a simple PowerShell script to set a site-specific environment variable value for ASPNETCORE_ENVIRONMENT:

Import-Module -Name WebAdministration
$siteName = "Site"
$envName = "Development"
Set-WebConfigurationProperty -PSPath IIS:\ -Location $siteName -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = $envName }

C
Christian

To extend on @tredder's answer you can alter the environmentVariables using appcmd

Staging

%windir%\system32\inetsrv\appcmd set config "staging.example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Staging'] /commit:APPHOST

Production

%windir%\system32\inetsrv\appcmd set config "example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Production'] /commit:APPHOST


Here is how to accomplish the same thing with Powershell on a build server without IIS installed. gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933
Specifying "staging.example.com" or "example.com" will only apply the variable to those specific websites. Omitting that will create a global variable for all websites on the server.
r
realMarkusSchmidt

What you need to know in one place:

For environment variables to override any config settings, they must be prefixed with ASPNETCORE_.

If you want to match child nodes in your JSON config, use : as a separater. If the platform doesn't allow colons in environment variable keys, use __ instead.

You want your settings to end up in ApplicationHost.config. Using the IIS Configuration Editor will cause your inputs to be written to the application's Web.config -- and will be overwritten with the next deployment!

For modifying ApplicationHost.config, you want to use appcmd.exe to make sure your modifications are consistent. Example: %systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /+"environmentVariables.[name='ASPNETCORE_AWS:Region',value='eu-central-1']" /commit:site

Characters that are not URL-safe can be escaped as Unicode, like %u007b for left curly bracket.

To list your current settings (combined with values from Web.config): %systemroot%\system32\inetsrv\appcmd.exe list config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore

If you run the command to set a configuration key multiple times for the same key, it will be added multiple times! To remove an existing value, use something like %systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /-"environmentVariables.[name='ASPNETCORE_MyKey',value='value-to-be-removed']" /commit:site.


note that with /commit:site the changes are written in the web.config, in order to save them in the ApplicationHost.config one should use /commit:apphost
-section:system.webServer/aspNetCore /-"environmentVariables. (with minus to remove environment variable) fails to be executed during Azure release pipeline. The error is hresult:80070032, message:Command execution failed. However clear config "Default Web Site/$(webSiteName)" -section:system.webServer/aspNetCore /commit:site works fine. It clears the whole aspNetCore section for the web site but it is not a problem since it is parametrized during the release.
B
Bartosz Lenar

@tredder solution with editing applicationHost.config is the one that works if you have several different applications located within virtual directories on IIS.

My case is:

I do have API project and APP project, under the same domain, placed in different virtual directories

Root page XXX doesn't seem to propagate ASPNETCORE_ENVIRONMENT variable to its children in virtual directories and...

...I'm unable to set the variables inside the virtual directory as @NickAb described (got error The request is not supported. (Exception from HRESULT: 0x80070032) during saving changes in Configuration Editor):

Going into applicationHost.config and manually creating nodes like this:

and restarting the IIS did the job.


I
Ismail Umar

I know a lot of answers has been given but in my case I added web.{Environment}.config versions in my project and when publishing for a particular environment the value gets replaced.

For example, for Staging (web.Staging.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <location>
        <system.webServer>
            <aspNetCore>
                <environmentVariables xdt:Transform="InsertIfMissing">
                    <environmentVariable name="ASPNETCORE_ENVIRONMENT"
                                         value="Staging"
                                         xdt:Locator="Match(name)"
                                         xdt:Transform="InsertIfMissing" />
                </environmentVariables>
            </aspNetCore>
        </system.webServer>
    </location>
</configuration>

For Release or Production I will do this (web.Release.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <location>
        <system.webServer>
            <aspNetCore>
                <environmentVariables xdt:Transform="InsertIfMissing">
                    <environmentVariable name="ASPNETCORE_ENVIRONMENT"
                                         value="Release"
                                         xdt:Locator="Match(name)"
                                         xdt:Transform="InsertIfMissing" />
                </environmentVariables>
            </aspNetCore>
        </system.webServer>
    </location>
</configuration>

Then when publishing I will choose or set the environment name. And this will replace the value of the environment in the eventual web.config file.


s
sjokkogutten

For those of you looking to this in an azure devops pipeline, this can be achieved by adding the PowerShell on target machines task and running the following script:

$envVariables = (
  @{name='VARIABLE1';value='Value1'},
  @{name='VARIABLE2';value='Value2'}
)

Set-WebConfigurationProperty -PSPath IIS:\ -Location $('mySite') -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value $envVariables

This is exactly what I was looking for. Thank you.
D
Dmitry Pavlov

To get the details about the error I had to add ASPNETCORE_ENVIRONMENT environment variable for the corresponding Application Pool system.applicationHost/applicationPools.

Note: the web application in my case was ASP.NET Core 2 web application hosted on IIS 10. It can be done via Configuration Editor in IIS Manager (see Editing Collections with Configuration Editor to figure out where to find this editor in IIS Manager).


l
lockedscope

I have created a repository for publishing IIS with the environment configuration in Web.config.

https://github.com/expressiveco/AspnetCoreWebConfigForEnvironment

Setup Get the sections from .csproj and .user.csproj files into your project files. Get the MyAspNetEnvironment.props, web.development.config and web.production.config files.

Get the sections from .csproj and .user.csproj files into your project files.

Get the MyAspNetEnvironment.props, web.development.config and web.production.config files.

Configuration Change the value of ASPNETCORE_ENVIRONMENT property in user.csproj relevantly.

Change the value of ASPNETCORE_ENVIRONMENT property in user.csproj relevantly.


This does not seem to provide a quality answer to the question. Please either edit your answer adding the overall details of this solution, or just remove it and post it as a comment to the question. Thanks!
M
Md. Nazrul Islam

I have modified the answer which @Christian Del Bianco is given. I changed the process for .net core 2 and upper as project.json file now absolute.

First, create appsettings.json file in root directory. with the content { // Possible string values reported below. When empty it use ENV variable value or Visual Studio setting. // - Production // - Staging // - Test // - Development "ASPNETCORE_ENVIRONMENT": "Development" } Then create another two setting file appsettings.Development.json and appsettings.Production.json with the necessary configuration. Add necessary code to set up the environment to Program.cs file. public class Program { public static void Main(string[] args) { var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); ***var currentDirectoryPath = Directory.GetCurrentDirectory(); var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json"); var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath)); var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();*** try { ***CreateWebHostBuilder(args, enviromentValue).Build().Run();*** } catch (Exception ex) { //NLog: catch setup errors logger.Error(ex, "Stopped program because of setup related exception"); throw; } finally { NLog.LogManager.Shutdown(); } } public static IWebHostBuilder CreateWebHostBuilder(string[] args, string enviromentValue) => WebHost.CreateDefaultBuilder(args) .UseStartup() .ConfigureLogging(logging => { logging.ClearProviders(); logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); }) .UseNLog() ***.UseEnvironment(enviromentValue);*** } Add the envsettings.json to your .csproj file for copy to published directory. Now just change the ASPNETCORE_ENVIRONMENT as you want in envsettings.json file and published.