- Home
- .NET tutorials
- Azure DevOps release pipeline for .NET Web API using IIS
Azure DevOps release pipeline for .NET Web API using IIS
Published: Friday 22 July 2022
An Azure DevOps release pipeline can be used to deploy a .NET website to IIS. It also allows us to set up a CI/CD process in Azure.
Before we think about creating a release pipeline, we need to have an Azure DevOps organization and project set up, as well as a build pipeline created. A build pipeline will checkout a Git repository from a version control hosting provider like GitHub, build and publish the application and deploy the build artifacts.
C# coding challenges
In this tutorial, we'll have a look at how to create a Azure DevOps release pipeline using YAML. The process will involve setting up an environment in Azure Pipelines and creating an agent on our deployment server. We'll also go through the steps of releasing an ASP.NET Core Web API to IIS.
Azure DevOps Environment
We have our web server setup which is a Windows 11 machine, and we'll be running the Web API using IIS. The goal here is set to up a release pipeline that will deploy our application to this server through Azure DevOps.
Inside our Azure DevOps project, we need to go into the Pipelines section and select Environments. Afterwards, we need to create an environment.
When creating a new environment, we need to specify a name, an optional description and and a resource. The environment name will need to be used in the pipeline that we will setup, so it's important that this is memorable. We are going to set the name as Windows 11 server. For the resource section, we'll select Virtual machines.
Next, we need to select the provider. By default, this should be set as Generic provider and is probably the only option that is available. We also need to select the operating system. As we have a Windows 11 server, we are going to select Windows. We also have the option to select Linux.
Installing the agent
Our next task is to run a Powershell script to register an Azure Pipelines Agent onto our server. We can do that by clicking on the copy icon, which will copy the script that we need to run.
On the deployment server, we need to open up a Powershell window (in administration mode), and paste the script into there.
Press enter to run the script. There are some options that we need to consider as the script is being ran. We should be able to press enter to all of them and use the default settings.
Once the script has successfully ran, it will create our Azure Pipelines Agent as a Windows Service. The service should be running.
The release pipeline
With our environment setup, and our Pipelines Agent installed, we can go ahead and create the release pipeline.
At this point, we must have a build pipeline setup in-order to deploy to our server. Checkout our how to create a build pipeline article with instructions on how to do this, as we will be following on from this tutorial.
Inside our project, we go to the Pipelines section, and go ahead and create a new pipeline.
When setting up a pipeline, we need to connect the source repository. Azure DevOps supports a number of version control hosting providers, including GitHub and BitBucket. Once we've selected one, we need to select which repository to use, and then configure the pipeline.
We'll select Starter pipeline, and we should find that there is already a azure-pipelines.yml
pipeline in our repo. This is used for our build pipeline. If this file exists in our repo, it will append a hypthen, followed by a 1
to the filename, so it will be called azure-pipelines-1.yml
.
We will go ahead and remove all the tasks, but keep the comments in there. At this point, we will save the file, which will be pushed to our repository.
Create the release pipeline
We are going to have a look at a number of YAML keys that we can use for our pipeline to deploy our ASP.NET Core Web API.
Trigger
With a build pipeline, we may wish to run it everytime a commit is made in our repo.
However, this wouldn't be the case for a release pipeline as we wouldn't want to run it until the build pipeline is complete.
As a result, we need to turn off the trigger. We can do that using the YAML trigger
key.
trigger:
- none
Variables
Next, we want to set up a variable. When creating an IIS website, we are going to call it AzureTestProject
. Throughout the pipeline, we are going to have to use this name reference. Subquently, we want to set it up as a variable, which we can do like this:
variables:
IISWebsiteName: 'AzureTestProject'
Resources
Afterwards, we want to create a link to our build pipeline. To do that, we can create a resource. Inside the resource, we reference the pipeline.
The pipeline
key in an alias and will be referred to in many instances within our release pipeline. In this instance, we are going to call it buildPipeline
. However, this can be anything you want it to be.
We need to reference the name of the project where the build pipeline resides. Using the project
key, this has to match the name of the project. In our instance, it will be AzureTestProject.
Afterwards we need to use the source
key to reference the pipeline. This references the name of the pipeline, and is case sensitive. So if the build pipeline is called Build pipeline, the source key's value must be Build pipeline
.
Finally, we want to set which branch we should be reading the build pipeline from. We can use the branch
key and set it to main
.
If we want to set up continuous deployment (CD) and run the release pipeline once a build pipeline has completed, we can set a trigger
key to true
. This trigger
key can also be used to select specific branches.
Here is the YAML script:
resources:
pipelines:
- pipeline: 'buildPipeline' # Alias for pipeline resource. Can be anything.
project: 'AzureTestProject' # This must match the name of the project
source: 'Build pipeline' # This must match the name of the build pipeline
branch: 'main'
trigger: true # Runs every time a build pipeline has completed
Deploy job
Next, we need to set up a job. The only job for this pipeline is to deploy the website. Within this job, we must declare the environment where the job is being performed. This will be on our deployment server.
Taking a look at the environment that we set up earlier, we named it Windows 11 server, and we installed it on a resource called DAVE, so we need set the environment as Windows 11 server.DAVE
.
We also need to set up a strategy, and for this, we are going to run this job once which will peform the deployment.
Here is the YAML snippet.
stages:
- stage: DeployWebsite
displayName: 'Deploy website'
pool:
vmImage: windows-latest
jobs:
- deployment: DeployWebsite
displayName: 'Deploy website'
environment: 'Windows 11 server.DAVE' # Name of the environment followed by the name of the resource
strategy:
runOnce:
deploy:
...
Download artifacts
Next, we have to create some steps into our job, and the first is to download the artifacts. For this we set a download
key, and this will refer to the alias that we gave to our build pipeline.
As we gave our build pipeline an alias of buildPipeline
, that is what we will refer to in our download.
We also need to specify the artifact name. When creating our build pipeline, it deployed the artifacts with a name of AzureTestProject
, so that is what we need to reference here.
stages:
- stage: DeployWebsite
displayName: 'Deploy website'
pool:
vmImage: windows-latest
jobs:
- deployment: DeployWebsite
displayName: 'Deploy website'
environment: 'Windows 11 server.DAVE'
strategy:
runOnce:
deploy:
steps:
- checkout: none
- download: 'buildPipeline' # The alias of our build pipeline
name: 'DownloadBuildArtifacts'
displayName: 'Download build artifacts'
artifact: 'AzureTestProject' # The name of the artifact from the build pipeline.
...
IIS deploy
Now it's a case of deploying our artifacts to IIS on our server.
Azure gives us a number of tasks for IIS which includes app management, and app deployment.
Stop IIS website
The first thing we want to do is to stop our IIS website. When creating a task, we wish to specify that we are stopping the website, and we can do that with setting the ActionIISWebsite
to StopWebsite
.
We are going to reference the variable IISWebsiteName
which we set earlier. This will be set as our StopStartWebsiteName
.
- task: IISWebAppManagementOnMachineGroup@0
name: 'StopIIS'
displayName: 'Stop IIS website - ${{ variables.IISWebsiteName }}'
inputs:
IISDeploymentType: 'IISWebsite'
ActionIISWebsite: 'StopWebsite'
StartStopWebsiteName: '${{ variables.IISWebsiteName }}'
Deploy IIS website
With our IIS website stopped, we can make the deployment. One of the inputs we must specify is the package. This is the full path of the artifacts that was downloaded. The format is as follows:
$(Pipeline.Workspace)\buildPipeline\AzureTestProject\RoundTheCode.AzureTestProject
$(Pipeline.Workspace)
= The path on the deployment server where the agent stores downloaded artifacts.buildPipeline
= The alias of the build pipeline.AzureTestProject
RoundTheCode.AzureTestProject
= The full path of the folder to where the deployment files are located.
Here is the YAML task:
- task: IISWebAppDeploymentOnMachineGroup@0
name: 'DeployIIS'
displayName: 'Deploy IIS website - ${{ variables.IISWebsiteName }}'
inputs:
WebSiteName: '${{ variables.IISWebsiteName }}'
Package: '$(Pipeline.Workspace)\buildPipeline\AzureTestProject\RoundTheCode.AzureTestProject'
TakeAppOfflineFlag: true
Start IIS website
With our app deployed, we can start the application. For this task, we use similar YAML code for stopping the website, but we change the ActionIISWebsite
input to StartWebsite
.
task: IISWebAppManagementOnMachineGroup@0
name: 'StartIIS'
displayName: 'Start IIS website - ${{ variables.IISWebsiteName }}'
inputs:
IISDeploymentType: 'IISWebsite'
ActionIISWebsite: 'StartWebsite'
StartStopWebsiteName: '${{ variables.IISWebsiteName }}'
The full YAML file
Here is the full YAML file for our release pipeline.
trigger:
- none
variables:
IISWebsiteName: 'AzureTestProject'
resources:
pipelines:
- pipeline: 'buildPipeline'
project: 'AzureTestProject'
source: 'Build pipeline'
branch: 'main'
stages:
- stage: DeployWebsite
displayName: 'Deploy website'
pool:
vmImage: windows-latest
jobs:
- deployment: DeployWebsite
displayName: 'Deploy website'
environment: 'Windows 11 server.DAVE'
strategy:
runOnce:
deploy:
steps:
- checkout: none
- download: 'buildPipeline'
name: 'DownloadBuildArtifacts'
displayName: 'Download build artifacts'
artifact: 'AzureTestProject'
- task: IISWebAppManagementOnMachineGroup@0
name: 'StopIIS'
displayName: 'Stop IIS website - ${{ variables.IISWebsiteName }}'
inputs:
IISDeploymentType: 'IISWebsite'
ActionIISWebsite: 'StopWebsite'
StartStopWebsiteName: '${{ variables.IISWebsiteName }}'
- task: IISWebAppDeploymentOnMachineGroup@0
name: 'DeployIIS'
displayName: 'Deploy IIS website - ${{ variables.IISWebsiteName }}'
inputs:
WebSiteName: '${{ variables.IISWebsiteName }}'
Package: '$(Pipeline.Workspace)\buildPipeline\AzureTestProject\RoundTheCode.AzureTestProject'
TakeAppOfflineFlag: true
- task: IISWebAppManagementOnMachineGroup@0
name: 'StartIIS'
displayName: 'Start IIS website - ${{ variables.IISWebsiteName }}'
inputs:
IISDeploymentType: 'IISWebsite'
ActionIISWebsite: 'StartWebsite'
StartStopWebsiteName: '${{ variables.IISWebsiteName }}'
Running the release pipeline
With our release pipeline set up, we can go ahead and run it. We can go ahead and press the blue "Run" button in the top-right hand corner of the screen.
This will run the tasks within our release pipeline. Assuming everything is working as it should be, our .NET web app will be deployed to our server and running in IIS.
See the deployment in action
Checkout our video tutorial, where we go ahead and create a release pipeline. We populate the YAML file with our tasks, and then run it.
Also checkout the ASP.NET Core Web API project used in this tutorial. Download it and use it to create a release pipeline. The Git repository will need to be forked into a Git account which can have access to the Azure DevOps project.