Skip to main content
ANVISoftware Solutions
Lesson 2 of 12Intermediate18 min

Runtime, SDK and Target Frameworks

By the end of this lesson

Decide which components a given machine needs and why.

This is the setup question that costs the most time across a team, and it is not because the concept is hard. It is because two downloads have similar names and the error message you get from choosing wrongly does not say which one you chose.

The SDK builds code. The runtime executes it. The SDK contains a runtime, so a machine with the SDK can do both. A machine with only the runtime can run a finished application and nothing else.

Same family, different jobs:

 SDKRuntime
ContainsCompiler, build engine, package client, project templates, the dotnet command — and a runtimeThe execution engine and the base class library assemblies
dotnet new, build, test, publishWorkNot available
Running a published applicationWorksWorks
Rough install sizeHundreds of megabytesTens of megabytes
Belongs onDeveloper machines and build agentsServers and production container images
Finding out what a machine actually has
Shell
# Which SDKs are installed, and where
dotnet --list-sdks

# Which runtimes are installed — note there are usually several lines per version
dotnet --list-runtimes

# Everything: the SDK in use, the host, the platform identifier, and both lists
dotnet --info

# The SDK version selected in the current folder, which global.json can change
dotnet --version
  • dotnet --list-sdks printing nothing while --list-runtimes prints several lines is the signature of a runtime-only machine. That is the state where dotnet build fails and running a published application succeeds.
  • The runtime list shows more than one entry per version because the shared framework is split. Microsoft.NETCore.App is the base platform; Microsoft.AspNetCore.App adds the web framework. A web application needs the ASP.NET Core runtime, which includes the base one.
  • dotnet --info reports the platform identifier for the machine, such as linux-x64 or win-x64. You need that string when producing a self-contained build.
  • dotnet --version can differ between folders. A global.json file pins which installed SDK is used for everything beneath it, which is how a team keeps build behaviour identical across machines.

The next distinction resolves most version confusion: a target framework is a promise you make at compile time, and the installed runtime is the reality at start-up.

The TargetFramework in your project file, net10.0 for example, states which version of the platform you are compiling against. It decides which library types and language features are available, and it is checked at compile time.

The runtime installed on the machine that runs your application is a separate fact, checked when the process starts. Nothing links the two except your deployment.

When the two do not match, the launch fails with a message naming the framework and version it wanted. What that message means is specific: the application was built expecting a major version of the platform that this machine does not have. The application is fine. The machine is missing a component.

What a version mismatch looks like, shortened
Shell
$ dotnet Anvi.Employees.Api.dll

# You must install or update .NET to run this application.
# Framework: 'Microsoft.NETCore.App', version '10.0.0'
# The following frameworks were found:
#   9.0.14 at [/usr/share/dotnet/shared/Microsoft.NETCore.App]

# Confirm the reading: the app wants 10, the machine has 9
dotnet --list-runtimes
  • The wording varies between versions, but the shape holds: what the application asked for, followed by what was available.
  • Within a major version the runtime rolls forward automatically. An application built against 10.0.0 starts happily on 10.0.7, which is why servers can take patch updates without anyone rebuilding.
  • It does not roll forward across major versions by default. A net10.0 application will not start on a 9 runtime, and it will not start on an 11 runtime either unless you opt in with a roll-forward setting.
  • Two fixes, and they are genuinely different decisions: install the matching runtime on the machine, or publish a self-contained build that carries its own.

The decision, machine by machine:

Your development machine
The SDK. Install the latest long-term support version unless a project pins another with global.json. Several SDK versions can sit side by side without conflict.
A build agent or CI runner
The SDK, at the version the build expects. If the agent has a newer SDK than your laptop, builds can differ — a global.json committed to the repository removes that variable.
A server running a framework-dependent build
The runtime, matching the major version your application targets. For a web application that means the ASP.NET Core runtime.
A server running a self-contained build
Nothing. The published output carries the runtime with it. You trade a larger deployment and your own patching responsibility for having no prerequisite.
A container image
Both, in separate stages. The build stage uses an SDK image; the final stage uses a runtime image and copies the published output into it. The shipped image never contains the compiler.

Summary

  • The SDK builds and runs; the runtime only runs. The SDK contains a runtime
  • Developer machines and build agents need the SDK; servers need the runtime or a self-contained build
  • TargetFramework is checked when you compile; the installed runtime is checked when the process starts
  • A mismatch message means the machine lacks the major version the application was built for — install it, or publish self-contained
  • Self-contained output has no prerequisite but moves runtime patching onto your release process

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Try it yourself

Read your own machine, then break it on purpose

Run dotnet --list-sdks and dotnet --list-runtimes and write down what you have, including which shared frameworks appear.

Now open a project file and change TargetFramework to a major version you do not have installed. Try to build, then read the error. Change it back.

Which of those two commands would have told you the answer fastest?

Show solution

The build fails with a message about the target framework or a missing reference pack, not about a runtime. That distinction matters: a compile-time failure means the SDK cannot find what it needs to build against, and a start-up failure means the machine cannot find what it needs to run.

dotnet --list-runtimes answers the start-up question. dotnet --list-sdks answers the build question. Getting into the habit of running the right one turns a confusing message into a two-second check.

Think about it

Why is self-contained not the default?

A self-contained build removes the need to install anything on the server. That sounds strictly better. Give two reasons it is not the default, and one situation where you would choose it anyway.

Show solution

Size is the obvious reason. Every deployment carries a full runtime, and several applications on one machine each carry their own copy instead of sharing the installed one.

Patching is the more important reason. With a framework-dependent build, a runtime security fix applied to the machine or the base image protects every application on it. With self-contained builds, each one needs rebuilding and redeploying. That is a process commitment, not a one-off choice.

It earns its place when you cannot control the target machine — a command-line tool you hand to other teams, an appliance, a build agent you do not administer. No prerequisite is worth real money there.

There is no single right answer. The point is that the choice moves patching responsibility, and a team should make it deliberately rather than by accident.

Knowledge check

Nothing is recorded and there is no score. The explanation appears either way.

A colleague reports that dotnet run fails with a message about no SDK being found, but the published application runs on the same machine. What happened?
Your application targets net10.0. The server has runtime 10.0.7 installed. What happens at start-up?

Saved in this browser only.