Publish a self-contained .NET app on Azure DevOps
Tags: dotnet, dotnetcore, csharp, azuredevops
Published: 2021-06-28 10:44:07

---
title: Publish a self-contained .NET app on Azure DevOps
published: true
description: Tutorial to build and publish a console application including the .NET (Core) framework from Azure DevOps Pipelines.
tags: dotnet, dotnetcore, csharp, azuredevops
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/po83m84h9phke91tcrf5.png
canonical_url: https://blog.elmah.io/publish-a-self-contained-net-core-app-on-azure-devops/
---

I had a problem today that I ended up spending quite some time resolving. We have some internal CLI's that we have been migrating to .NET Core lately. Rather than having to clone the code and build it when needed, I wanted to set up an automated build, producing a self-contained console app on our Azure DevOps server.

When setting up builds on Azure DevOps, I pretty much follow the same pattern over and over again. The first step is usually setting up a `dotnet restore` task:

![](https://blog.elmah.io/content/images/2020/01/dotnet-restore.png)

Notice the custom feed selected in the Feeds to use section. The reason I'm mentioning this is that it will cause problems in a minute.

Next, I add a `dotnet build` step:

![](https://blog.elmah.io/content/images/2020/01/dotnet-build.png)

So far so good. To produce a self-containing output, you can use `dotnet publish` together with the `--runtime` option. In my case I want to produce a self-containing program for 64 bit Windows, why the command looks like this:

```console
dotnet publish --runtime win-x64
```

Adding that command as a build step is easy:

![](https://blog.elmah.io/content/images/2020/01/dotnet-publish.png)

Unfortunately, the build failed on Azure DevOps with the following error:

> error NETSDK1047: Assets file '...\obj\project.assets.json' doesn't have a target for '.NETCoreApp,Version=v5.0/win-x64'. Ensure that restore has run and that you have included 'net5.0' in the TargetFrameworks for your project. You may also need to include 'win-x64' in your project's RuntimeIdentifiers.

When looking through my `csproj` file, the project doesn't include a runtime as proposed by the error message:

```xml
<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
```

To fix the error, I simply add a `RuntimeIdentifiers` element:

```xml
<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net5.0</TargetFramework>
  <RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
</PropertyGroup>
```

This fixed the build error just to reveal a new error in the `dotnet publish` step:

> C:\Program Files\dotnet\sdk\5.0.301\NuGet.targets(123,5): error : Unable to load the service index for source .../_packaging/Elmah.Io.Shared/nuget/v3/index.json.
C:\Program Files\dotnet\sdk\5.0.301\NuGet.targets(123,5): error :   Response status code does not indicate success: 401 (Unauthorized).

Remember the `dotnet restore` step which pointed out a custom NuGet feed to (also) restore packages from? Unfortunately, neither `build` or `publish` has this option, why I need to disable restore on those steps (no need to restore and build multiple times anyway). This can be done by modifying the build step:

```console
dotnet build --runtime win-x64 --no-restore
```

This tells the build command to build for the `win-x64` runtime and don't do NuGet restore. We need the runtime parameter since `dotnet publish` will no longer restore and build if required. The `--no-restore` parameter instructs build not to restore NuGet packages.

Similar, I extended the publish command:

```console
dotnet publish --runtime win-x64 --no-build mycli.csproj
```

By including the `--no-build` parameter, neither restore or build is executed as part of this step.

The changes produce a nice self-contained .NET 5 console app. The final step is to publish the generated zip-file using a *Publish build artifacts* step:

![](https://blog.elmah.io/content/images/2020/01/publish-build-artifacts-2.png)

When anyone needs the newest build of the CLI, he/she can download it by navigating to the most recent build and clicking the *Artifacts* button:

![](https://blog.elmah.io/content/images/2020/01/artifacts-explorer.png)

## Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ [Error Monitoring for .NET Web Applications](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/publish-a-self-contained-net-core-app-on-azure-devops/