I recently began working with AppVeyor as a deployment platform for my .NET deployments.  It has proved to be a great tool for implementing build and deploy automation for .NET Framework and .NET Core applications since it treats .NET as a first-class citizen.  Most configurations with AppVeyor are almost automatic, however I was missing automated variable substitution by deploy environment that I became so comfortable with when using other continuous integration tools like Octopus Deploy.  

Why do I need Variable Substitution?  

It allows for making environment specific Connection Strings, API credentials, and other configurations separate from your application code.  This software architecture idea comes from the third section of the tweleve factor app methodology, which you can read more about here: https://12factor.net/.  You'll find this feature in a lot of modern web frameworks, not just in ASP.NET Core.

Let's go over how Octopus Deploy handles appsettings.json variable substitution. For a JSON based file, Octopus Deploy has an out-of-the-box feature to apply configuration values per environment.  It can replace root level values, hierarchical properties, and even array values using a special syntax.  More documentation on how you can implement it in Octopus Deploy and how it works here: https://octopus.com/docs/deployment-process/configuration-features/json-configuration-variables-feature.  

AppVeyor does not support this directly in their product for JSON files.  They do support variable substitution using a parameters.xml file to target a web.config file in an ASP.NET deployment (https://www.appveyor.com/docs/deployment/web-deploy/#parametersxml).  However, it seems Microsoft is moving towards JSON based configurations with .NET Core.  

The Script

The way I got around this was by leveraging a part of the AppVeyor deployment pipeline.  AppVeyor uses a Powershell script named "deploy.ps1" to drive and automate any deployment tasks on the target machine.  I've written a Powershell script to replace appsettings.json configuration values to match your environment.  (If you're having trouble with the script, please see the update at the end of this article.)

The script utilizes the user-defined environment variables that AppVeyor writes to the target machine for deployments.  I use a prefix ($env:APPLICATION_PREFIX) for grabbing an Array of those variables, then loop through them.  Each iteration of the loop searches the target appsettings.json file (or any other JSON based configuration file you feed it) for matching properties.  If a property matches the name of an environment variable (with the environment prefix stripped out), then the value of the environment variable will be written to the output file.

Now what this doesn't support that you can find in Octopus Deploy is the array variable substitution.  Currently this handles root level and hierarchical property values, but I'd like to add array support some time in the future.  I'd also like to expand this to use recursion so it can support more than a property depth of one.

Feel free to use this script for your own purposes.  I had trouble finding one like it, so hopefully you find this suitable for what you need to get started. If you find a way to improve it, I'd love to hear about it!  Send an email to mitch.gollub@gmail.com. Thanks for reading!

UPDATE 1/31/21:

If you've been having trouble with the above script, @eivindivine was able to make some adjustments and get it working.  He shared his example here:

Check out the link to his gist for more information on what changed!