Deploy .NET API to Azure App Service through Azure DevOps
Tags: dotnet, azure, devops, pipelines
Published: 2021-12-03 14:50:27

In this article we are going to learn how to implement continuous integration and continuous deployment to a .NET API through Azure DevOps.

##Prerequisites:
* Visual Studio 2022 with .NET 6 SDK
* SQL Server Database
* Account on [Azure DevOps Services](https://azure.microsoft.com/en-us/services/devops) and [Azure Portal](https://azure.microsoft.com/en-us/features/azure-portal)
* Download or clone the base project from [here](https://github.com/cristofima/StoreCleanArchitecture-NET/releases/tag/v2.1.0)

## 1. Create Azure SQL Database
Click in the sidebar icon and go to `Resource groups`.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hfbx1n13at1ldul24fjf.png)

Click on Create.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ag3pnch1mg2810hkszl.png)

Type a name for the resource group, then click on `Review + create ` / `Create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeojp1z0hu7v01qy4xl8.png)
  
For this example, I used `Demo-StoreCleanArchitecture` for the resource group.

Now, from the side bar, go to `SQL databases`.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cf5q2mofc5cluful2tx.png)

Click on Create.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwhydtxyvw1z1zl8nia7.png)

Type the database name and create a server if you haven't one.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4jyxc49flq80dvp83a7.png)
  
Let's create a server. Follow these steps:
- Type a unique server name
- From `Authentication method`, select `Use SQL authentication`
- Type `Server admin login` and `password`, then click on `Ok`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27jp85pxidr10ch0p7wa.png)
 
From `Compute + storage`, click on `Configure database`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ol9in9xy5sfaztpes0l.png)
 
As you can see, the default `service tier` has a lot of estimated cost per month (231.28 USD). Let's select other `service tier` with less cost.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/louv7sc9e27hvmklnp02.png)
 
Select `Basic`, this is for less demanding workloads. And now the cost is too low (4.99 USD).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/komgs5p68hu46a3iwxzi.png)
 
Then, click on `Review + create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojqzi3ryslpwj296iuk3.png)

You can see a summary of all the features you are going to implement in this resource. Click on `Create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzapo00vzp6v72ox9gyd.png)

Let's wait until the database is created. Then click on `set server firewall`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/seyvu19tzpne9icmutin.png)

Let's add a rule to allow connections to this database only from our IP address. Click on `Add client IP`. Also enable `Allow Azure services and resources to access this server`. Then click on `Save`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7p9ny0l723io82nt5c7j.png) 
 
To test if we are allowed to connect to this database. Open SQL Server Management Studio. From `Object Explorer`, click on `Connect` / `Database Engine`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbtdhrxkb99qtfmhmbeq.png)

Enter the credentials and click on `Connect`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/286g71t5d85qgz6sjscn.png) 

As you can see, the connection was successful.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01s686p6m7jlid4duelo.png)
 
## 2. Create Azure App Service
From the side bar, select `App Services`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vl0pjagxgqijdditcc70.png)
 
Click on `Create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/in0yyuuynnabggqxfk46.png)
 
Follow these steps:
- Select the Resource group
- **Name:** specify an unique name
- **Runtime stack:** .NET 6 (LTS)
- **Operating System:** Linux

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zug72zgjqsl5ka9rczr.png)
 
If it's a new `App Service Plan`, we can change the `Sku and size`, clicking on `Change size`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lis8c5fybfn4f66m8j8k.png)
 
Select `F1` plan from Dev/Test and click on `Apply`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nokvozgjg7ipu6zcqfz3.png)
 
Then, click on `Review + create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rj2rohhu6zncxjf5jyto.png)
 
You can see a summary with all the features of our Web App. Click on `Create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oa0zw4v6ezadgk7s1xmm.png)
 
After the Web App is created. Go to the resource, in `Settings` section, click on `Configuration`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53x26tu4umozsky4gnbf.png)
 
Go to `Connection strings`, click on `New connection string`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxngvgw86js76v8m1xha.png)

In the dialog, enter `DefaultConnection` in `Name`, select `SQLAzure` in `Type` and add the connection string in `Value`. Then click on `Ok`.

> Server=`<server_name>`.database.windows.net;Database=`<database_name>`;User ID=`<username>`;Password=`<password>`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kpj143lijfjbltaokymx.png)
 
As you can see, the connection string was added. Click on `Save`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7rpt2hh9g6fk4gisny9.png)
 
## 3. Create project on Azure DevOps and create Build and Release pipelines

### 3.1. Update .NET application
Before to go to Azure DevOps Services, first we need to do a change in the .NET application. In the Infrasctructure project, in `DependencyInjection.cs` file, add the following below `services.AddScoped<IProductRepository, ProductRepository>();`.

```csharp
var serviceProvider = services.BuildServiceProvider();
try
{
  var dbContext = serviceProvider.GetRequiredService<StoreContext>();
  dbContext.Database.Migrate();
}
catch
{
}
```

This will apply all the pending migrations to the database.
Commit the changes.

### 3.2. Create Build Pipeline
Go to Azure DevOps Services. At the right, click on `New project`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmae4rqs70r1qfxx5r8m.png)

Specify a project name. Select the visibility you want. Click on `Create`.
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uz4nm0o7ed3l0zf3a4un.png)

Go to `Pipelines`, click on `Pipelines`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq4yxyx9vohfoxdvo7hd.png)
 
Click on `Create Pipeline`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6hfjz22fyclazg3d6fsg.png)
 
Click on `Use the classic editor`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/057nyiarq6104201mf3r.png)
 
Select `GitHub`. Type a connection name, then click on `Authorize using OAuth`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5ockymcuwd2vy2wksgg.png)
 
Sign in with the credentials from the account you have the repository.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jlilskf8k2qw8ktn7ak.png)
 
Once you authorized to connect to your GitHub account. You can link your repository.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fixilaohkbpken75jgoe.png)
 
Search the repository and click on `Select`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfmv4favow6haznqvqr9.png)
 
Once the repository and branch are selected, click on `Continue`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5v72jmoocsxijcuf5ct.png)
 
Select the `ASP.NET Core` template and click on `Apply`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gha8gv79i20gi3icrkxk.png)

Set the pipeline name as `CI` and the agent specification in `windows-2022`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8i0z70j6r9zup8lx2153.png) 
  
You can change the name for the agent job as well. Click on the plus icon from Agent Job.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izlz3brflgw8qmzcewhi.png)
 
Select `Use .NET Core` and click on `Add`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qz1n8mk20y300fgfrgvx.png)
 
This will add a new task to the final. Move it to the top and set version as `6.x`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcswa43uparc63cdki07.png)

Click on the `Publish` task. Uncheck `Publish web projects`, click on `Path to project(s)` / `Unlink`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vyjmcj022qwygmxapq1m.png)

Type `**/src/Store.WebApi/*.csproj` in `Path to project(s)`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yjacikgytyq23ulm6ees.png)

Click on `Save & queue`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvrog9bvd8yf2kdyvfk3.png)
 
You can specify a save comment, then click on `Save and run`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8in3ym5h3p16ikhdh54.png)
 
Now, the job is running. Click on the job.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew8cvgvtr5xckkial661.png)
 
Let's wait until the job is finalized. As you can see it was successful.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m9fb2f4llzyf0act0kj2.png)

If we go to the GitHub repository, we can see there is a `green check mark` in the last commit.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpor9ildhvxwz32gv6wt.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhokkvau4ihrvt6wq4ky.png)

Go to the list of pipelines, click on the three dots to the right. edit.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m906y0mop9zcj6t75cc1.png)
   
Go to `Triggers` section. Enable `continuous integration` and click on `Save`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hy8f1717bi6n9esk2ey8.png) 

### 3.3. Create Release Pipeline
From `Pipelines` section, click on `Releases`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8ihhhbcae8udkawbrmf.png)
 
Click on `New pipeline`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70b8zek9je1ze1bp5sko.png)
 
Select `Azure App Service deployment` template and click on `Apply`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ir0rew0qp7s357alwl9u.png)
 
Follow these steps:

1. Change pipeline name to `Deploy to Azure`
2. Change stage name to `Production`
3. Click on `Add an artifact`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vog9fu7hu0irwf8sme1z.png)

It should be selected `Build` as `Source type`. In `Source`, select `CI` and click on `Add`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytx0bvi5hpn77drr5l6a.png)
 
Once the Artifact is added, click on the button with the lightning icon.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6dedrgf97ss7wt280qb.png)
   
Enable `Continuous deployment trigger`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxknjk3b1kkzorsv95yr.png)
 
Go to the `Production` stage and click on `1 job, 1 task`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkxjf0i2bxmlb6pnrhpa.png)

Select one of your `Azure subscriptions` and click on `Authorize`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pz9w5sb4p4xf2mo531jz.png)

Then, select `Web App on Linux` in `App type`. Select the `app service name` you created in section 2 and in `startup command` type `dotnet Store.WebApi.dll`. Click on `Run on Agent`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wl6e805ja6rvnlw1r119.png) 
 
Select `windows-2022` in `Agent Specification`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chyu03srthhd9qxq1k1o.png)

Scroll down and in `Artifact download` you can see it's selected `_CI` artifact and there is a folder named drop with `Store.WebApi.zip` file. Click on `Save`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ned89rrku8u6n5m6ht55.png)
 
Click on `Ok`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpemhvtjb0nt6pmf8yl4.png)

Finally. Lest's create our first release. Click on `Create release`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkmbjp8bw4psj7wx588b.png)

Click on `Create`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/td0tkvc32nixt8xsi3g1.png)
 
Let's wait until the Pipeline finalizes.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tf0ucgbah5k30vtbocm2.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbmzrnsahbff3pj7itkk.png)

As you can see the `Production` stage was succeeded.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1ty66gwz8hery8o4bvi.png)
    
Let's test the api. Since we used F1 App Service plan. We have to wait some seconds for the first request of the day.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l10gpyf5jmugjw1kdy6.png)

### 3.4. Create dashboard
We are going to create a dashboard to display the statistics for build and release pipelines.
Go to `Overview` section and click on `Dashboards`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oe4qeaudex8e2wxca3li.png)

Click on `Add a widget`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/30924rbwgde369shhe38.png)
 
Select `Deployment status` and drop it to the dashboard.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m1pl2pwh10zd4pv0kc8.png)
 
Configure the widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6x1vaeva99il4tgi76w.png)

Select the build pipeline, release pipeline and last column. Click on `Save`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f43jmcyjzr5u7ldaa37f.png)

Add `Build Health Details` widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jqwpdinil7uigzro8jx.png)

Configure the widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gp8mi4ovgero8dkcx2te.png)

In `Definition`, select the build pipeline (CI).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ci38xvcthlffb2j7yc8o.png)
 
Add `Build History` widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3sr5lfgnb6ks8qco4oh9.png)
 
Configure the widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55szfdzjhcvxqlufkdrj.png)

Select the build pipeline (CI).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1htawjh7jo3yc0q87fpw.png)

Add `Build Health Overview` widget.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xsksec1ae9veqhj9p8t.png)
   
In the configuration, select the build pipeline (CI).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5k0rqiig8fubfogjfo4h.png)
 
Once you added the four widgets, click on `Done Editing` at the top of the dashboard.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bnyxj3t4k7wtb2u9rtk.png)

This is the final result. You can add all the widgets you want, but for this example, these ones are enough.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsc5fkah7u99vyxrahrh.png) 

You can find the source code [here](https://github.com/cristofima/StoreCleanArchitecture-NET).

You can watch the webinar in Spanish [here](https://www.youtube.com/watch?v=-LU8eNS8cCA).

**Thanks for reading**

Thank you very much for reading, I hope you found this article interesting and may be useful in the future. If you have any questions or ideas that you need to discuss, it will be a pleasure to be able to collaborate and exchange knowledge together.