9

I'm trying to deploy an ASP.NET Core application to IIS using VSTS with the following tasks

enter image description here

However, after much googling and browsing through MS docs I couldn't find a way to set environment variables for the deployment. The variables I set in the release definition in environment scope aren't getting set as environment variables.

enter image description here

Any idea how to achieve that?

ubi
  • 4,041
  • 3
  • 33
  • 50
  • 1
    Based on this thread https://developercommunity.visualstudio.com/content/problem/165842/set-environment-variables.html?childToView=167553#comment-167553, you have a workaround, you can post an answer and accept it as an answer. On the other hand, what's the detail log if trying with my solution? – starian chen-MSFT Dec 14 '17 at 03:25
  • The deployment is successful so there's no error in the logs. But the transformation is not applied. I wonder if it's because `xdt:Tranform` is not applicable to the `environmentVariable` node? Btw, Intellisense flags that attribute as an error. – ubi Dec 14 '17 at 03:32

6 Answers6

6

The environment variables you set in VSTS are just used for the deployment itself (ie anything that VSTS is doing such as building your application or running unit tests), but the runtime application will use whichever ones are on the server hosting it.

You will need to set the environment variables on the IIS server that VSTS is deploying to if you want your deployed application to use them as well. Microsoft docs show how to set this depending on your server: Setting the environment

Update in response to comments:

The reccommended way to set environment variables is on the machine itself - ie. log in to the IIS server you are deploying to and add the ASPNETCORE_ENVIRONMENT environment variable there in system properties -> advanced settings -> environment variables

If for some reason you aren't able to do this, you can set them in the Web.config file (according to that documentation). If you are always setting the same value you should be able to just put what you need in the Web.config like so

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

If you really need the XML transforms (which, honestly, I'm not sure you do in this situation - this is for altering the Web.config file at deployment time based on the build configuration. As somebody else mentioned, with asp.net core the reccommended config setup is appsettings[.environment].json files which are automagically loaded based on the matching machine level ASPNETCORE_ENVIRONMENT env variable), you need to actually define the transformations in a transform file using the correct syntax and have it replace the parts you want to change. This is obviously the more difficult option.

See: How to: Transform Web.config When Deploying a Web Application Project for creating the transformation files and Web.config Transformation Syntax for Web Project Deployment Using Visual Studio for the configuration syntax if you choose to go down that path

Something like this (unable to currently test but this should give you an idea - note the transform namespace on the transform file and the xdt: attributes). I believe the transform file that gets loaded matches the build configuration which you may need to configure as part of the VSTS task:

Web.config

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

Web.Release.config (transform file for build configuration "Release")

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <aspNetCore ...>
      <environmentVariables>
        <environmentVariable xdt:Transform="Replace" xdt:Locator="Match(name)" name="ASPNETCORE_ENVIRONMENT" value="Production" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Kirlac
  • 684
  • 6
  • 18
  • Thanks - from the link you provided it appears environment variables can only be set in the `web.config`. Now, how do you transform `web.config` file per environment. e.g. if I have `` in the `web.config` file, is there a way to override it per each environment? I have the `XML variable substitution` and `XML transformation` options ticked in the VSTS task (https://learn.microsoft.com/en-us/vsts/build-release/tasks/deploy/iis-deploy) but they aren't doing the transform. – ubi Dec 12 '17 at 03:11
  • It's been a while since I've worked with web.config files, but i believe you create a file per environment eg. `*..config` so you could create a `Web.config` and a `Web.Development.config` and a `Web.Production.config` and the XML transformation setting will build your final config based on the environment (which I think in this case will be determined by your VSTS environment variables). See: https://learn.microsoft.com/en-us/vsts/build-release/tasks/transforms-variable-substitution#xml-transformation – Kirlac Dec 12 '17 at 03:57
  • @ubi With Asp.Net core project, it's better to use appsettings.json and appsettings.[environment name].json files, after that it can override the related value in appsettings.json with appsettings.[environment name].json per to environment (ASPNETCORE_ENVIRONMENT). On the other hand, I'd suggest asking separate questions in new forum threads. Thus, forum readers may recognize questions and answers easily. – starian chen-MSFT Dec 12 '17 at 05:56
  • Actually, the issue I'm facing is the variable (`ASPNETCORE_ENVIRONMENT`) I set in `web.config` doesn't get transformed. – ubi Dec 12 '17 at 06:14
  • 1
    @starian chen-MSFT I think you misunderstood the issue here. Ubi is trying to set the `ASPNETCORE_ENVIRONMENT` variable on deployment (presumably to load the correct appsettings.json file) – Kirlac Dec 13 '17 at 01:15
2

For ASP.NET Core 1.x projects with a web.config you can use the below.

Since your deployment has a "Dev" environment, commit to your project the following config file:

web.Dev.config

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <aspNetCore>
      <environmentVariables xdt:Transform="InsertIfMissing" />
      <environmentVariables>
        <environmentVariable xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" name="ASPNETCORE_ENVIRONMENT" />
        <environmentVariable xdt:Transform="Replace" xdt:Locator="Match(name)" name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>
  • The above will create the environmentVariables section in your web.config if it does not already exist.
  • Replace "Dev" in web.Dev.config with other environment names as necessary.
  • ASPNETCORE_ENVIRONMENT used as an example above, change for other variables.
  • Remove the xmlns="" attribute from the configuration element above if your web.config does not have the same namespace attribute on the configuration element.

In your project.json, add under publishOptions => include:

"web.dev.config"

In VSTS deployment make sure to check "XML transformation" under the IIS Web App Deploy task: XML transformation checkbox

Tolga
  • 2,643
  • 1
  • 27
  • 18
2

Here is the powershell script I use within Release pipeline (I don't like setting ASPNETCORE_ENVIRONMENT within the build)

arguments:

-p $(System.DefaultWorkingDirectory)\$(Build.DefinitionName)\drop\testbld-Test\web.config -e Development

Inline Script:

param ([string]$p,[string]$e)
$doc = new-object System.Xml.XmlDocument
$location = "$p"
$doc.Load($location)
$subNode = $doc.CreateElement("environmentVariable")
$node = $doc.CreateElement("environmentVariables")
$doc.SelectSingleNode("//aspNetCore").AppendChild($node)
$doc.SelectSingleNode("//environmentVariables").AppendChild($subNode)
foreach($nd in $subNode) {$nd.SetAttribute("name", "ASPNETCORE_ENVIRONMENT");$nd.SetAttribute("value", "$e");}
$doc.Save($location)
Post Impatica
  • 14,999
  • 9
  • 67
  • 78
2

I add it as an argument during the "Publish" step of the build:

/p:EnvironmentName=Development

enter image description here

Then it will be added to the web.config of the build output.

denyo85
  • 69
  • 5
1

Refer to these steps below:

  1. Set config files properties (e.g. web.config, web.QA.config), Copy to Output Directory: Copy if newer)
  2. .NET Core task (Command: restore)
  3. .NET Core task (command: build)
  4. .NET Core task (Command: publish; Check Publish Web Projects option; Arguments: --configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory); Check Zip Published Projects option)
  5. Publish Build Artifacts (Path to publish:$(build.artifactstagingdirectory))
  6. Open release definition, change environment name (e.g. QA, match the config file name)
  7. IIS Web Deploy task: (Package or Folder: $(System.DefaultWorkingDirectory)\**\*.zip; Check XML transformation option (it is based on Environment name to look for transform source file)
  8. Then the web.[environmentname].config file (e.g. web.QA.config) will be transformed to web.config file.

You also can do it through XDT transform task, (the files can’t be in the zip file, so un-check Zip Published Projects option: step4, and archive files through Archive Files task in release)

starian chen-MSFT
  • 33,174
  • 2
  • 29
  • 53
1

Another approach to setting environment variables (other than using the XML transform approach) is to add a Powershell task which uses appCmd command to set environment variables in the ApplicationPool scope

C:\Windows\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='XyzPool'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Dev']" /commit:apphost
ubi
  • 4,041
  • 3
  • 33
  • 50