DevOps, Release Pipeline, Console App, Replace Endpoints
Tags: devops, csharp, dotnet
Published: 2019-09-26 12:23:50

So recently, I had to work on a project that required me to create pipelines (build, release) on Azure DevOps.

I had a simple console application which called two WCF services to authenticate for security, retrieve (i.e. database) and then give me a list of users I needed to send out SMS's to.

I then created my build, here’s how it looks. The build executes in sequence, from top to bottom.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/99rqk3koedfpsw1cjpoc.png)

I then created my release pipeline, here’s how it looks.
 
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2e5a7nfdibwd5d7fupvy.png)

File Transform task basically points to the file path to the package or folder which points to the bin/Release folder and the target files that need to be transformed to XML, in this case there’s two (i.e. dll.config and exe.config)

Copy Files to task specifies the source folder to copy from after the file transform, and then specifies the target folder to copy to.

The last task is a PowerShell Script to run the console app project named Replace App Config Endpoints, which will then replace all the endpoint addresses.

I’ve done a build and a release for a normal website before and all I had to do was to create a SetParameters.xml file and define all the tokens/variables I needed to be replaced.

So here’s the problem I faced, I couldn’t find anything online to do this for me and the SetParameters.xml replaced app settings and connection strings, I’m sure there is but my Googling skills failed me that time.

PROBLEM: I needed to replace the WCF endpoint addresses for the specific environments (i.e. QA, Production) variable values.

SOLUTION: I created a console application to do this for me which will be run by the PowerShell Script.

Please note, Environment.GetEnvironmentVariable() will retrieve the value of an environment variable from the current process. We can specify different values based on whether the Environment is QA or Production.

Here’s how it looks

args expects the full path(s) to the config we need to replace the service endpoint addresses for e.g. "C:\Users\Projects\projectname1\bin\Debug\projectname1.exe.config" 
"C:\Users\Projects\projectname2\bin\Debug\projectname2.exe.config"  

        static void Main(string[] args)
        {
            try
            {
                foreach (var appConfigFilePath in args)
                {
                    var doc = new XmlDocument();
                    doc.Load(appConfigFilePath);
                    XmlNodeList endpoints = doc.GetElementsByTagName("endpoint");

                    foreach (XmlNode item in endpoints)
                    {
                        doc.GetElementsByTagName("endpoint").Cast<XmlNode>()
                            .FirstOrDefault(n => n.Attributes["name"].Value == item.Attributes["name"].Value).Attributes["address"].Value = Environment.GetEnvironmentVariable(item.Attributes["name"].Value);
                    }

                    doc.Save(appConfigFilePath);
                }
            }
            catch (Exception)
            {
                // catch exception and log error
            }
        }


If anyone has a different approach or can extend this please feel free to point me in the right direction.