Publish to IIS, setting Environment Variable

144,165

Solution 1

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.

  1. Go to your application in IIS and choose Configuration Editor.
  2. Select Configuration Editor
  3. Choose system.webServer/aspNetCore (RC2 and RTM) or system.webServer/httpPlatform (RC1) in Section combobox
  4. Choose Applicationhost.config ... in From combobox.
  5. Right click on enviromentVariables element, select 'environmentVariables' element, then Edit Items. enter image description here
  6. Set your environment variables.
  7. Close the window and click Apply.
  8. 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.

Solution 2

Update web.config with an <environmentVariables> section under <aspNetCore>

<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>

Solution 3

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>

Solution 4

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.

Solution 5

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:

enter image description here

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.

Share:
144,165

Related videos on Youtube

drpdrp
Author by

drpdrp

Updated on July 22, 2022

Comments

  • drpdrp
    drpdrp almost 2 years

    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?

    • Oleg
      Oleg over 8 years
      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.
  • Grady Werner
    Grady Werner over 8 years
    It appears that in ASP.NET 5 RC1, the environment variable was changed to Hosting:Environment.
  • GeekzSG
    GeekzSG over 8 years
    How do we set "Load User Profile" to true when we deploy this to Azure Web App?
  • drpdrp
    drpdrp over 8 years
    @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/…
  • b.pell
    b.pell over 8 years
    @GradyWerner For RC2 they're changing it (as of now) to ASPNET_ENVIRONMENT ;-)
  • Dean North
    Dean North about 8 years
    If you are publishing through visual studio's msdeploy. Then you can put <IISCommand>Staging</IISCommand> in your .pubxml file and it will deploy using the specified IIS command even though you cant specify it in the publish UI.
  • S. Rasmussen
    S. Rasmussen about 8 years
    @DeanNorth - This is golden!! Works like a champ! Thanks for sharing!
  • Mark G
    Mark G almost 8 years
    @b.pell It appears it's now ASPNETCORE_ENVIRONMENT :)
  • Mark G
    Mark G almost 8 years
    For step 3 I used system.webServer/aspNetCore instead.
  • b.pell
    b.pell almost 8 years
    Thanks for the head's up. We're in the process of converting to RC2 as I write this.
  • NickAb
    NickAb almost 8 years
    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/…
  • Trevor Daniels
    Trevor Daniels almost 8 years
    Thanks @NickAb, that avoids having to update web.config every deploy. I've updated my answer.
  • Christian
    Christian almost 8 years
    Please check NickAb answer it is simpler and does not involve special users and global environment variables.
  • Christian
    Christian almost 8 years
    I'm having trouble with doing this from powershell I keep getting Target configuration object '/system.webServer/aspNetCore/environmentVariables/environme‌​ntVariable 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/environmen‌​tVariable -name ASPNETCORE_ENVIRONMENT -value Staging what Im I missing?
  • Christian
    Christian almost 8 years
    I went back to what I knew and used appcmd instead.
  • Peter Kottas
    Peter Kottas about 7 years
    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.
  • Coruscate5
    Coruscate5 about 7 years
    For reasons unknown, even with the system Environment Var set, if this section is not modified, .NET Core seems to get "stuck" & doesn't respect the machine setting - this was the only thing that worked
  • NickAb
    NickAb about 7 years
    System environment variables are inherited by processes at start. So if you change some env variable during run of your application you would not be able to see this changes by default. For system env var changes to take effect you will need at least to restart the site, maybe pool, or even IIS service, depending on how IIS creates processes. This needs to be tested.
  • Coruscate5
    Coruscate5 about 7 years
    @NickAb - I restarted the machine, still didn't pick it up. It must have been getting set somewhere during startup, but I can't find where it could have been. Obviously now it is respecting the IIS setting.
  • madoxdev
    madoxdev about 7 years
    You made my day. Thanks
  • Kugel
    Kugel about 7 years
    What a great out of the box experience, when you have to create another layer of configs to manage configs of a framework
  • Brad Gardner
    Brad Gardner almost 7 years
    Won't the settings added via the Configuration Editor get wiped out on the next deployment?
  • NickAb
    NickAb almost 7 years
    @brad-gardner if changes are made to Applicationhost.config instead of web.config, then changes will be persisted between deployments.
  • The Red Pea
    The Red Pea almost 7 years
  • The Red Pea
    The Red Pea almost 7 years
  • NickAb
    NickAb almost 7 years
    @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.
  • NickAb
    NickAb almost 7 years
    @the-red-pea you can edit web.config in your project as shown in your second link, but in that case you will have same values for environment variables despite of target IIS server, e.g. both Staging and Production server will have same ASPNETCORE_ENVIRONMENT value if set via web.config in project. In this case, to get different values on different IIS servers you will have to use web.config transformations to change values. on deployment.
  • user3103701
    user3103701 over 6 years
    Here is how to accomplish the same thing with Powershell on a build server without IIS installed. gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933
  • Frank Cannon
    Frank Cannon over 6 years
    Works for Asp.Net Core 2.0
  • Dave Shinkle
    Dave Shinkle over 6 years
    Thank you for this!
  • aruno
    aruno almost 6 years
    Is anybody actually using this method for production? it gets blown away every time you deploy! are you creating a web.config file and using transforms or something else? this answer is not great at all :-(
  • sɐunıɔןɐqɐp
    sɐunıɔןɐqɐp almost 6 years
    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!
  • deadlydog
    deadlydog almost 6 years
    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.
  • Curtis Buys
    Curtis Buys over 5 years
    @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' }
  • Angel Yordanov
    Angel Yordanov over 5 years
    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
  • colinwurtz
    colinwurtz almost 5 years
    Step 4 is very key
  • PatsonLeaner
    PatsonLeaner over 4 years
    Thanks alot @NickAb, you are a day saver! a00% working on my asp.NET Core 2.2 Hosting in IIS 10. Many Thanks
  • oleksa
    oleksa over 4 years
    -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.
  • Leff
    Leff over 4 years
    @colinwurtz even though I set the variable in ApplicationHost.config, IIS manager starts to show it on both Web.config and ApplicationHost.config pages right after webapp publication, although there's no ASPNETCORE_ENVIRONMENT variable set in the application Web.config file. Application gets some kind of "Staging;Staging" or "Production;Production" string as the value of EnvironmentName.
  • colinwurtz
    colinwurtz over 4 years
    @Leff is ASPNETCORE_ENVIRONMENT the variable you set in ApplicationHost.config? I think IIS manager forwards anything from ApplicationHost to Web.Config, but it persists that way between deployments/publishes of the site.
  • Leff
    Leff over 4 years
    @colinwurtz Yes, I set the variable in ApplicationHost.config using IIS manager. I suppose this behaviour is the bug of IIS 8.5. As far as I know IIS 10 does not act like this. We've decided to configure the variable using separate application pool accounts for a while.
  • JensB
    JensB over 4 years
    I could not get this to work with Applicationhost.config after having set the Web.config file first and then removing it from web.config. The key was to redeploy as if you just remove the setting from Web.config using the editor it puts a </clear> tag in the file which removes all environment settings. After redeploy, and a new blank web.config it all worked.
  • Just code
    Just code over 4 years
    You are saviour bro!
  • c-sharp-and-swiftui-devni
    c-sharp-and-swiftui-devni over 3 years
    This doest appear to work in .net core 3.1 its still not set for me.
  • Abhinav Galodha
    Abhinav Galodha over 3 years
    @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?
  • Priyank Panchal
    Priyank Panchal over 3 years
    This is exactly what I was looking for. Thank you.
  • Muflix
    Muflix over 3 years
    @NickAb I just tried to change ASPNETCORE_ENVIRONMENT on the fly when the app was running and the change applied immediately, so no restart was needed. Also appsettings.<environment>.json was also reloaded immediately :-) (asp .net core 3.1.8 and IIS 10)
  • JustAMartin
    JustAMartin about 3 years
    Good idea. I prefer setting every variable specific to the environment instead of piggybacking everything onto ASPNETCORE_ENVIRONMENT and environment JSON files. This way app pool env variables can be controlled by system admins who do not want to deal with JSON and also do not want to store production access data in JSON files. Also, you do not want to commit your production env data in Git for every team developer to see.
  • makinyelure
    makinyelure about 2 years
    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.