Allow remote access to IISExpress for development in VS

When you want to test your website and check it remote you see the error:

Bad Request – Invalid Hostname


HTTP Error 400. The request hostname is invalid.

First thing to do is to find the correct applicationhost.config file. This file can be found in

the solution directory under .vs/<Solution name>/config. This file contains an entry under the tag <sites> for the site with the config that is applied in IISExpress.

This enables binding for the IIS:

    <bindings>
      <binding protocol="http" bindingInformation="*:29136:localhost" />
      <binding protocol="https" bindingInformation="*:44343:localhost" />
    </bindings>

Above configuration only allows localhost to access the IISSExpress site.

Change it to:
        <bindings>
          <binding protocol="http" bindingInformation=":29136:" />
          <binding protocol="https" bindingInformation=":44343:" />
        </bindings>
to allow remote machines to access the site.

Azure click once publish for test and production CI/CD

Change config and sign a click once deployment for test in an Azure build application:

I have the following release pipeline in Azure:

Continuous Integration pipeline that will build for every check in on master branch. This build will trigger a Continuous Delivery pipeline that will deploy the release for the click once application to test. The same installation wil be deployed to production after approval in test on this pipeline.

I want the same build that I tested to go to production. The click once is compiled for release. The app.config I have in source is the production version. So once installed the app will default be configured to connect to production datasources.

For test however I want the app.config to be replaced with a app.config.debug version. This is a app.config that contains the test and debug datasources.

After putting this config file in the deployment the signature for the click once is no longer valid. I resigned the click once manifest for the changed config with a tool from Microsoft .NET SDK.

I used the mage.exe (from .NET framework Tools). Path for my installation: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\mage.exe.

I added 3 files to the source directory:

mage.exe
app.config.debug
ACertificateFile.pfx. This pfx is the same I used in the project to sign the manifest file.

After adding these 3 files to the source folder I added a copy step in the build pipeline to add these files to the app.publish folder:

And a script to update the app.config and resign the manifest has to be executed before copying the files to the local deployment server.

@echo on
for /f “delims=” %%F in (‘dir “$(system.defaultworkingdirectory)_Bla.WPF.BLA-.NET Desktop-CI\$(System.TeamProject)-$(Build.BuildNumber)\Application Files” /B /AD’) do set deployDir=%%F
set “to=$(system.defaultworkingdirectory)_Bla.WPF.BLA-.NET Desktop-CI\$(System.TeamProject)-$(Build.BuildNumber)\Application Files\%DeployDir%”
set “from=$(system.defaultworkingdirectory)_Bla.WPF.BLA-.NET Desktop-CI\$(System.TeamProject)-$(Build.BuildNumber)”

copy /Y “%from%\App.config.debug” “%to%\BLA.exe.config.deploy”

ren “%to%*.deploy” *.
“%from%\mage” -sign “%to%\BLA.exe.manifest” -CertFile “%from%\ACertificateFile.pfx”
“%from%\mage” -update “%to%\BLA.exe.manifest” -CertFile “%from%\ACertificateFile.pfx”
“%from%\mage” -update “%from%\BLA.application” -appmanifest “%to%\BLA.exe.manifest” -CertFile “%from%\ACertificateFile.pfx”

ren “%to%*.*” *.*.deploy
ren “%to%*.manifest.deploy” *.
del “%from%\mage.exe”
del “%from%\App.config.debug”
del “%from%\ACertificateFile.pfx”

Simple unit tests in Visual Studio solutions

In Visual Studio it is really simple to add unit tests that are automatically run in your build script. Right click your solution to add a test project:

Add a few test methods:

Check this Step-By-Step for an explanation:

https://visualstudiomagazine.com/articles/2013/07/29/test-driven-development-with-visual-studio-2012.aspx

Check this link for some Unit test basics:

https://docs.microsoft.com/en-us/visualstudio/test/unit-test-basics?view=vs-2017

/// <summary>
/// Test if flipcoins throws as many times as requested
/// </summary>
[TestMethod()] public void FlipCoinsTest1Times()
{
//Arrange
int odd, even;
int times = 1;

//Act
CoinFlipper coinFlipper = new CoinFlipper();
coinFlipper.FlipCoins(times, out odd, out even);

//Assert Assert.IsTrue(times == odd + even);
}

Open Test explorer window

Right click a selection of tests and select “Run selected tests”.

When the tests are OK, we can check in the solution. Default the Build in Azure will run libraries with names containing *test*.

The results for this solution: 8 tests passed.

How to set up a local deployment for an Azure build application

*Important note: This solution will only work when you do NOT have a .gitignore file in your repository*

Configure a local agent

First requirement is that you set up a local agent that will be used for the local tasks.

How to configure local build and deploy agents is explained here:

https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=vsts

The result should look somewhat like this:

To control this agent you can choose to install it as a service on Windows.

Or you can choose to run the agent from the command line. To start and stop the agent I added two scripts:

Start.cmd:

Start.cmd:
cd c:
cd \EK-VSTS-Agent
start “EK-VSTS Azure agent” .\run.cmd
exit

Stop.cmd:

taskkill /FI “WindowTitle eq EK-VSTS Azure agent*” /T /F

Setup a build and release pipeline in Azure

Goto Pipelines in your Azure Devops project and click on new pipeline. My example uses a project named WPFDatasetWithSQL.

*Important note: This solution will only work when you do NOT have a .gitignore file in your repository*

Click continue and choose .Net Desktop and click Apply.

If you want to build the solution using a hosted machine keep the “Agent pool” set on “Hosted VS2017”. If you need local components to build you could choose to use a local machine or set up the required components in this build script.

For this example I have no need for extra components and I will keep the Agent pool on Hosted VS2017.

We are going to change a few setps in this script:

1 Set the MSBuild Arguments to /target:publish. This changes the MSBuild to add a app.publish to the build directory for click once deployment.

2 Change the step Copy Files to add the app.publish folder to the artifacts folder.
Display name = Copy Files to: $(build.artifactstagingdirectory)
Source Folder = $(Build.SourcesDirectory)\src\BLM\bin\$(BuildConfiguration)\app.publish
Contents = **\**

3 Change the artifact name.
Display name = Publish Artifact: $(System.TeamProject)-$(Build.BuildNumber)
Artifact name = $(System.TeamProject)-$(Build.BuildNumber)

Click Save and keep the default name.

Set up a release pipeline

Now we will set up a release pipeline in which we can control and manage releases for this application.

Click on Releases in the menu and click New pipeline.

Choose a Empty job template. The release pipeline is going to contain not much more than a few copy tasks.

For starters we will have to choose an artifact. Choice is simple, we are going to use the artifacts from the build pipeline. Select the Source Build pipeline set up in the previous step and finish this by clicking the Add button below.

Next step in this release pipeline is a deployment to “Test”. For this purpose we will rename the default “Stage 1” to “Test”. For this, clicking the Stage1 image (not on the link to job with task) will open a properties window. Rename Stage1 to Test and click save right top in the corner.

Now click the link to job and task in the Test stage. Click the agent job and change the agent pool to the pool where you added the local agent. In my example I added the local agent to a pool named “local machine”.

Now we will add a job to copy the publish folder to a local directory. Click on the puls sign next to “Agent job” and search for “Copy Files”

Select The task added below Job agent and fill in the details:

Select The task added below Job agent and fill in the details:
Display name = Copy Files to: c:\drop\$(System.TeamProject)\$(Release.EnvironmentName)\$(Release.ReleaseName)\
Source Folder = $(system.defaultworkingdirectory)_WPFDatasetWithSQL-.NET Desktop-CI * This last directory name is the build pipeline name
Target Folder = c:\drop\$(System.TeamProject)\$(Release.EnvironmentName)\$(Release.ReleaseName)\

The source folder will contain the pipeline name for the build pipeline preceded by an underscore:

Click save in top right hand corner.

Now we are going to add the production stage and the required copy jobs for this stage.

Click on releases in the left menu and click edit.

Click “Clone” in Test stage. And rename this new stage “Copy of Test” to “Production”. Click the task details and here I added System.TeamProject to the source folder name. This removes the build number from the destination name.

Next click the plus sign for the “Agent job” to add a command line script. With this command line we will first clean the install folder before we copy the new release in that location. The command line script is rd /S /Q c:\drop\$(System.TeamProject)\Install\

Last task for this job is to add a second “Copy Files” task. This task will copy the publish content in the install folder.

For the first run disable the Command line script because the folder will not yet exist. This will cause an error if the command is executed while the directory does not exist. After the first run the command can be enabled.

Last option is to add an approval trigger on production. A test manager or a group of testers can be allowed to approve the release after testing.

Another nice feature is to enable continuous integration and continuous deployment in Azure. For this go to the build pipeline and click the checkbox for “Enable continuous integration” in the tab “Triggers”.

Second, go to release pipeline click the continuous deployment trigger and enable continuous deployment every time a new build is available. Click save.

First two times the deployment failed. I checked the logging and fixed some typing errors.

After approving the release the install folder will be updated with the required binaries.

All done. Enjoy.