← Back to Articles         
Using dotnet restore, build, test, and publish

Using dotnet restore, build, test, and publish

Published on 08 Oct 2026     5 min read Azure DevOps
ASP.NET Core Build Pipeline

Using dotnet restore, build, test, and publish in Azure CI Pipelines

1. What are these commands?

In an ASP.NET Core CI pipeline, four important .NET CLI commands automate the process of preparing, compiling, testing, and packaging an application.

Command

Purpose

dotnet restore

Downloads required NuGet packages

dotnet build

Compiles the application and checks for compilation errors

dotnet test

Executes automated tests

dotnet publish

Generates deployable application files

These commands are generally executed sequentially in Azure Pipelines.

2. How do they work?

Developer Pushes Code
          |
          v
Azure DevOps CI Pipeline
          |
          v
1. dotnet restore
   Download NuGet Dependencies
          |
          v
2. dotnet build
   Compile the Application
          |
          v
3. dotnet test
   Execute Automated Tests
          |
          v
4. dotnet publish
   Generate Deployment Files
          |
          v
Publish Pipeline Artifact
          |
          v
Available for CD Pipeline

3. Explanation of Each Command

A. dotnet restore

Purpose: Restore all NuGet dependencies required by the application.

dotnet restore MyApplication.sln

How it works:

  • Reads project files and NuGet configuration.

  • Resolves package dependencies.

  • Downloads missing packages from configured NuGet feeds.

  • Uses the local NuGet cache when packages are already available.

  • Generates or updates dependency information in obj/project.assets.json.

For example, if the ASP.NET Core application uses Entity Framework Core and Serilog, restore ensures the required packages are available.

Important: If package restoration fails, the pipeline stops.

B. dotnet build

Purpose: Compile the source code and validate that the application builds successfully.

dotnet build MyApplication.sln --configuration Release --no-restore

How it works:

  • Compiles C# source code.

  • Checks compilation errors.

  • Builds referenced projects in dependency order.

  • Generates assemblies such as .dll files.

  • Reports compiler warnings and errors.

Example output:

MyApp.Domain.dll
MyApp.Application.dll
MyApp.Infrastructure.dll
MyApp.API.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Important: --no-restore avoids repeating the restore step.

C. dotnet test

Purpose: Execute automated tests to verify application functionality.

dotnet test tests/MyApp.Tests/MyApp.Tests.csproj \
  --configuration Release \
  --no-build

How it works:

  • Discovers tests from the test project.

  • Executes unit tests using the configured test framework, such as xUnit, NUnit, or MSTest.

  • Reports passed, failed, and skipped tests.

  • Returns a failure status when tests fail.

Example output:

Total tests: 25
Passed:      24
Failed:       1
Skipped:      0

Test Run Failed.

Important: --no-build avoids recompiling the test project, assuming it was built in the previous step.

D. dotnet publish

Purpose: Prepare the application for deployment.

dotnet publish src/MyApp.API/MyApp.API.csproj \
  --configuration Release \
  --no-build \
  --output ./publish

How it works:

  • Collects compiled application assemblies.

  • Includes required runtime dependencies.

  • Copies applicable configuration and content files.

  • Generates deployment-specific files.

  • Places everything in the specified output directory.

Example output:

publish/
│
├── MyApp.API.dll
├── MyApp.API.deps.json
├── MyApp.API.runtimeconfig.json
├── appsettings.json
├── appsettings.Production.json
├── web.config              (for IIS targets)
└── Other dependencies

The exact output depends on the deployment target and publish settings.

Important: --no-build is appropriate when the application has already been built using compatible settings. dotnet publish otherwise performs a build automatically.

4. Azure Pipelines YAML Example

trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'

steps:

# Step 1: Checkout
- checkout: self

# Step 2: Install .NET SDK
- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '8.0.x'

# Step 3: Restore
- script: dotnet restore MyApplication.sln
  displayName: 'Restore Packages'

# Step 4: Build
- script: >
    dotnet build MyApplication.sln
    --configuration $(buildConfiguration)
    --no-restore
  displayName: 'Build Solution'

# Step 5: Test
- script: >
    dotnet test tests/MyApp.Tests/MyApp.Tests.csproj
    --configuration $(buildConfiguration)
    --no-build
  displayName: 'Run Unit Tests'

# Step 6: Publish
- script: >
    dotnet publish src/MyApp.API/MyApp.API.csproj
    --configuration $(buildConfiguration)
    --no-build
    --output $(Build.ArtifactStagingDirectory)/publish
  displayName: 'Publish Application'

# Step 7: Publish Artifact
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: '$(Build.ArtifactStagingDirectory)/publish'
    artifact: 'drop'
    publishLocation: 'pipeline'

The pipeline generates an artifact named drop, containing the published ASP.NET Core application files.

5. Important Differences

Feature

Restore

Build

Test

Publish

Downloads NuGet dependencies

Yes

Implicitly*

Implicitly*

Implicitly*

Compiles application

No

Yes

By default

By default

Executes unit tests

No

No

Yes

No

Generates deployable output

No

No

No

Yes

Common CI order

1

2

3

4

*Build, test, and publish can implicitly restore dependencies unless disabled using options such as --no-restore. Test and publish can also skip building when configured appropriately.

6. Interview Questions and Answers

Q1. Why do we execute dotnet restore before dotnet build?

To ensure all required NuGet packages are available before compilation.

Q2. Does dotnet build automatically execute dotnet restore?

Yes. By default, dotnet build performs an implicit restore unless --no-restore is specified.

Q3. What is the difference between dotnet build and dotnet publish?

dotnet build compiles the application, while dotnet publish prepares the compiled application and dependencies for deployment.

Q4. Does dotnet test build the project automatically?

Yes, by default. We can use --no-build when the test project has already been compiled.

Q5. Why do we use --no-build and --no-restore in CI pipelines?

To avoid repeating operations that have already completed successfully, reducing unnecessary build time.

Q6. What happens if dotnet test fails?

The CI pipeline normally stops, and the publish and artifact-generation steps are skipped.

Q7. Is dotnet publish the same as publishing an Azure Pipeline Artifact?

No. dotnet publish generates deployable application files. PublishPipelineArtifact@1 uploads those files to Azure DevOps for later use.

 

7. Interview-Ready Answer

In Azure DevOps CI pipelines, I use four main .NET CLI commands to build and prepare ASP.NET Core applications.

First, dotnet restore downloads the required NuGet dependencies. Next, dotnet build compiles the entire solution in Release mode.

After successful compilation, dotnet test executes automated unit tests. If any test fails, the pipeline stops.

Finally, dotnet publish generates the deployment-ready application files. These files are then uploaded to Azure DevOps using the Publish Pipeline Artifact task.

I use --no-restore and --no-build where appropriate to avoid repeating operations and improve pipeline performance.

Remember this sequence:

dotnet restore
      ↓
dotnet build
      ↓
dotnet test
      ↓
dotnet publish
      ↓
PublishPipelineArtifact@1
      ↓
Deployment Artifact

Key interview point: dotnet publish creates the deployable files, whereas PublishPipelineArtifact@1 stores those files in Azure DevOps.

← Back to Articles