1. Create an Azure Web App and a configuration file to build it
  2. Set up the project on GitHub and CircleCI
  3. Deploy the project to Azure Web App

Automating the deployment of a new web application and the release of feature updates can improve the productivity and efficiency of your development team. Automation also minimizes or even eliminates repeated manual deployments, which introduce the risk of human error during this critical part of the development process. Automation is a worthy goal, but the variety of frameworks and languages used by developers can make automating deployment a challenge.

Microsoft Azure Web Apps is a platform as a service (PaaS) that lets you publish Web apps running on multiple frameworks and written in different programming languages. You can then use a CI/CD tool to build, test, and deploy web applications for a faster release cycle, more efficient development, and higher-quality code.

In this tutorial, I will show you how to set up a continuous deployment pipeline to deploy an ASP.NET Core application to an Azure Web App service. We will use the Azure CLI orb for authentication and to directly deploy our application.

Prerequisites

You will need these to get the most from this tutorial:

Our tutorials are platform-agnostic, but use CircleCI as an example. If you don’t have a CircleCI account, sign up for a free one here.

Cloning the demo project

Your first step is to use Git to clone an API built with ASP.NET Core. Run this command:

git clone https://github.com/CIRCLECI-GWP/deploy-aspdotnetcore-to-azure.git

Next, go to the root of the new folder created by the previous command. Run the application:

cd deploy-aspdotnetcore-to-azure

dotnet watch run

You may get an error about the compatibility of the framework version.

ASP.NET Core version error

By default, the .NET framework application runs on the version that it was built with. The demo application was built with ASP.NET Core version 3.1. The error will occur if you are running a different version. Find out what version is installed on your computer using this command:

dotnet --version

If the output is a version other than version 3.1, you can fix it. Go to the root of the application and open the dotnet-core-sample.csproj file. Update it like this:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp6.0</TargetFramework>
  </PropertyGroup>
</Project>

Replace 6.0 with the version shown earlier from your terminal. Then, run the project again with the dotnet watch run command.

dotnet run watch results

The application will be live on http://localhost:5000. Navigate to this endpoint http://localhost:5000/weatherforecast to review the JSON response.

API Response

Reviewing the deployment strategy

Now that you have the application running locally, it is a good idea to review your deployment strategy. There is no need for any project code changes other than including the configuration file to set up deployment for CircleCI.

In chronological order, we will:

  1. Create an Azure web app
  2. Create a configuration file to build the application on CircleCI
  3. Push the project to a repository on GitHub
  4. Set up the project on CircleCI
  5. Provide Azure credentials and authenticate using the Azure CLI orb
  6. Use Git to set up deployment URL
  7. Deploy our project to Azure Web App

Creating an Azure web app

If you do not have one already, create an account on Azure. Then go to your Azure portal dashboard and click Create a resource to create a new service instance.

Click create resources

Next, click Web App from the Popular list.

Select Web App

You will be redirected to the Create Web App page. Select an Azure subscription and a resource group. Create a new resource group if you have not done that.

Save Web App

Now, enter a friendly, unique name for your web app. For this tutorial, I have used dotnet-core-sample. Update other fields as shown in the previous illustration.

Click Review + create, then Create. Wait while Azure sets up the web app environment.

Deployment In Progress

Once the process is completed, you will have a web app ready to host your ASP.NET Core application.

Application in App Services

Adding the CircleCI configuration file

In this step, we will create the pipeline configuration for CircleCI using the Windows orb and the Azure CLI orb.

To begin, create a folder named .circleci at the root of your project. In the new folder, create a file named config.yml. In the new file, add:

version: 2.1
orbs:
  azure-cli: circleci/azure-cli@1.2.0
  windows: circleci/windows@2.2.0
jobs:
  build:
    description: Build application with Release configuration
    executor:
      name: windows/default
    steps:
      - checkout
      - restore_cache:
          keys:
            - dotnet-packages-v1-{{ checksum "dotnet-core-sample.csproj" }}
      - run:
          name: "Install project dependencies"
          command: dotnet.exe restore
      - run:
          name: "Build Application according to some given configuration"
          command: dotnet.exe build --configuration Release
      - run:
          name: "Publish to a subfolder"
          command: |
            dotnet.exe publish --configuration Release --output WebAPIFolder
      - persist_to_workspace:
          root: ~/project
          paths:
            - WebAPIFolder
  login-to-azure-and-deploy:
    executor: azure-cli/azure-docker
    steps:
      - azure-cli/install
      - azure-cli/login-with-user:
          alternate-tenant: false
      - attach_workspace:
          at: ~/project
      - run:
          command: az webapp deployment source show --resource-group sample-dotnet-core --name sample-dotnet-core-application
      - run:
          name: "Deploy Web App to Azure"
          command: |
            az webapp deployment source config-local-git --resource-group sample-dotnet-core --name sample-dotnet-core-application
workflows:
  build-and-deploy:
    jobs:
      - build
      - login-to-azure-and-deploy:
          requires:
            - build

This configuration might seem a bit complex, so I will try to break it down for you.

First, it defines and pulls in the orbs we are using for this project:

  • The circleci/azure-cli@1.2.0 orb is used to install, initialize, and log into the Azure command-line interface. The Azure CLI gives you access to a set of commands to create and manage Azure resources.
  • The circleci/windows@2.2.0 orb gives you tools to build Windows projects such as the .Net framework.

The next part of the configuration specifies two different jobs:

  • build
  • login-to-azure-and-deploy

The build job uses the windows/default executor, which checks out our project from GitHub, installs the project’s dependencies, and publishes the application to a new subfolder named WebAPIFolder. Another step in this job is persist_to_workspace, which uses the workspace feature to move data from a particular job in a workflow to a later job that might need the same data.

In this case, we want the folder housing the published version of our project WebAPIFolder to be available in the next job without rebuilding the project.

The login-to-azure-and-deploy job uses azure-cli/default to install Azure CLI and provides the step to authenticate Azure users. Then it attaches the folder that was stored earlier. The job then uses the Azure CLI to configure the Git URL that will connect with our Azure web app.

The last part of the workflow specifies that the login-to-azure-and-deploy should not run until the build job is complete.

Connecting the application to CircleCI

The next step is to set up a repository on GitHub and link the project to CircleCI. Review Pushing a project to GitHub for instructions.

Log in to your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

Click Set Up Project next to your dotnet-core-sample project.

Replace the resource group with yours.

Set up project

You will be prompted to either write a new configuration file or use the existing one in your project. Select the existing one and enter the name of the branch where your code is housed on GitHub. Click Let’s Go.

Select Config

Your first workflow will start running:

  • The build job will pass
  • The login-to-azure-and-deploy will fail

The complete steps for the build job

The login-to-azure-and-deploy job will fail because we have not yet specified the Azure credentials.

Login build job

To fix that, create an Azure Service Principal and add output as environment variables. Click Project Settings.

Project Settings

Click the Environment Variables button on the left sidebar and create these variables:

  • AZURE_SP_TENANT is the name of the environment variable storing the tenant ID for the Service Principal.
  • AZURE_SP is the name of the environment variable storing the full name of the Service Principal.
  • AZURE_SP_PASSWORD is the name of the environment variable storing the password for the Service Principal.

AZ CLI create service principal

Learn how to create an Azure service principal with the Azure CLI.

Go back to the dashboard. Click Rerun Workflow from Failed.

Rerun job

When the build has finished running, you can review the output.

Remote URL

This is the local URL automatically generated for you to use for deployment to your Azure web app. The format of the URL is https://<username>:<password>@sample-dotnet-core-application.scm.azurewebsites.net/sample-dotnet-core-application.git.

The next step is to create your deployment credentials and update the configuration file. Note that the deployment credentials are not the same as the Azure authentication credentials.

Updating the configuration file

In this step, you will update the config file and use Git to deploy to the generated URL. To begin, return to the portal to create a new credential for deployment so that Git does not prompt for a password.

From the side menu bar, Click Deployment Center, then Local Git / FTP Credentials. Scroll to the User Scope section.

Set deploy credential

Enter a username or use the default one. Enter a password and re-enter it to confirm.

Click the Save button at the top.

Replace the content of .circleci/config.yml with this:

version: 2.1
orbs:
  azure-cli: circleci/azure-cli@1.2.2
  windows: circleci/windows@2.2.0
jobs:
  build:
    description: Build application with Release configuration
    executor:
      name: windows/default
    steps:
      - checkout
      - restore_cache:
          keys:
            - dotnet-packages-v1-{{ checksum "dotnet-core-sample.csproj" }}
      - run:
          name: "Install project dependencies"
          command: dotnet.exe restore
      - run:
          name: "Build Application according to some given configuration"
          command: dotnet.exe build --configuration Release
      - run:
          name: "Publish to a subfolder"
          command: |
            dotnet.exe publish --configuration Release --output WebAPIFolder
      - persist_to_workspace:
          root: ~/project
          paths:
            - WebAPIFolder
  login-to-azure-and-deploy:
    executor: azure-cli/azure-docker
    steps:
      - azure-cli/install
      - azure-cli/login-with-user:
          alternate-tenant: false
      - azure-cli/login-with-service-principal
      - attach_workspace:
          at: ~/project
      - run:
           command: az webapp deployment source show --resource-group sample-dotnet-core --name sample-dotnet-core-application
    # - run:
      #     name: "Deploy Web App to Azure"
      #     command: |
      #       az webapp deployment source config-local-git --resource-group sample-dotnet-core --name sample-dotnet-core-application

      - run:
          name: "Deploy Web App to Azure"
          command: |
            az webapp deployment source show --resource-group sample-dotnet-core --name sample-dotnet-core-application
            cd ~/project/WebAPIFolder/
            git init
            git config --global user.email "motukadominic@gmail.com"
            git config --global user.name "dominicmotuka"
            git add .
            git commit -m "Deploy Azure Web Application"
            git remote add azure https://$GIT_USERNAME:$GIT_PASSWORD@sample-dotnet-core-application.scm.azurewebsites.net/sample-dotnet-core-application.git
            git push azure master --force
workflows:
  build-and-deploy:
    jobs:
      - build
      - login-to-azure-and-deploy:
          requires:
            - build

The update to the configuration file includes Git, sets a remote URL to reference the link we generated earlier, and pushes to Azure.

Replace the GIT_USERNAME and GIT_PASSWORD placeholders with the credentials you created earlier in Azure for local Git.

Note: If you have used any special character (like @ or $) in your password, there will be an error. To prevent this error, use the HTML Encoding Reference equivalent of it.

Almost done! Once again, push your code to GitHub.

It is a successful build!

Testing the application

Visit your application at https://dotnet-core-sample.azurewebsites.net/weatherforecast. Your application was deployed.

Your successfully deployed application

Conclusion

The increasing variety of frameworks and languages used by you and your team could keep you from moving to a fully automated deployment process. In this tutorial, we showed that you can set up a functional deployment pipeline using the Windows and Azure orbs. That pipeline successfully deployed an ASP.NET Core application to the Azure Web Apps hosting platform.

Share the results of your work with your development team to start the conversation about replacing manual deployments with automation. Deploying even a complex application can be done, and the lower risk of human error, increased efficiency, and higher quality code is well worth the investment.

I do hope that you found this tutorial helpful. The complete source code can be found here on GitHub.


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Read more posts by Olususi Oluyemi