← Home
.NETPlatform and runtimeReported by candidates

.NET Framework vs .NET Core vs .NET 5 and later: what is the difference, why did Microsoft change it, and which would you use today?

29 reports in the question index (8 linked below), almost all first technical rounds: Yovant (3), Nayan India (2), PwC, Infosys, Deloitte, HCLTech, UST, NeoSOFT and others. Asked as "what is .NET Framework", ".NET vs .NET Core" and "why did .NET 5 drop Core".

Say this first · about 30 seconds
Make it yours · UDC Finance arrears rules, shared by an FIS plugin and an Azure API (invented example)
The code, simplified

Invented to show the shape. Tap Next to follow one build that makes two DLLs.

UDC.sln · where these 2 files sit
  • Udc.Arrears/
Udc.Arrears.csproj · line 1 · 1 of 3A project file: it tells dotnet build what to build. The SDK is the toolkit that builds .NET code.

Fix later in your repo Example written for this card: invented, not from a real codebase.

Say it out loud, then check

Show the 30-second answer
  • .NET Framework is the original version, from 2002. It runs only on Windows, it is installed once per machine as part of Windows, and its latest version, 4.8.1, came out in 2022. Microsoft still patches it, but plans no new features.
  • .NET Core, from 2016, was a rewrite: open source, cross-platform, so it runs on Windows, Linux and macOS, and much faster. Each app carries or names its own version, so two apps on one server can run different versions side by side.
  • With version 5, Microsoft dropped the word Core and skipped the number 4, so nobody would confuse it with Framework 4 point x. So .NET 5, 6, 8 and 10 are simply the next versions of .NET Core, one platform going forward. Even numbers are long-term support, three years; odd numbers get two.
  • In practice, ASP.NET Core gives you Kestrel as the built-in web server, dependency injection built in, and settings from appsettings dot json and environment variables instead of the old web config file. Some old parts never came across, like Web Forms pages and WCF services.
  • On BMW FS, our Azure services are on .NET 8 and run on Linux , which is cheaper. But the plugins we write for the FIS core stay on Framework 4.8, because the FIS host loads them. Code both sides need sits in a library built for both. For anything new, I pick the current LTS, .NET 10.
Check your answer: tick what you said

You said 0 of 8

Then add your example: UDC Finance arrears rules, shared by an FIS plugin and an Azure API (invented example)
  • Situation: at UDC Finance in New Zealand, the arrears rule (how many days late a payment is before a fee) lived in an FIS plugin. The FIS core is a .NET Framework 4.8 host, so the plugin must be Framework too. The new customer-portal API on Azure is .NET 8, and it needed the same rule. The portal team had copied the code, and the two copies had already drifted by one day.
  • What I did: I moved the rule into one class library and made it multi-target: one project file lists two target frameworks, net48 and net8.0. One build makes two DLLs (compiled code files), one for each world. The plugin uses the 4.8 one; the API uses the .NET 8 one.
  • Result: one copy of the rule, one set of tests, and both sides agree again. The build also proves the code works on both: if I use something .NET 8 has and 4.8 doesn't, an API or a newer C# feature, the 4.8 build fails.
  • What I'd say: Framework and .NET can share code. You target both in one project, or target .NET Standard 2.0 (a fixed list of APIs both sides promise to have), and you keep Framework only where a host forces it.

See it

1/7Before: the API runs inside IIS on Windows, on the one .NET Framework the machine has.

In plain words

The senior answer · about 2 minutes
The difference, in my words
  • .NET Framework is the Windows-only original. It is part of Windows, so a machine has only one 4.x, and an update to it changes every app on that server at once. Its latest version is 4.8.1, from 2022. It still gets security fixes with Windows, but nothing new is planned.
  • .NET Core was Microsoft starting again: open source, runs on Linux and macOS as well as Windows, and much faster. Each app names its own version, or ships with it, so two apps on one server never fight over the runtime. From version 5 it is just called .NET, so .NET 8 and 10 are the same line as .NET Core 3.1.
What changes when you build an API
  • In ASP.NET Core, the app is a normal program with a Program.cs. It starts Kestrel, its own web server, so it doesn't need IIS; on Windows you can still host it in IIS, which by default runs it in-process, without Kestrel. Dependency injection is built in, so the add-on DI containers like Unity or Autofac we used to wire in by hand are gone. Settings come from appsettings.json, environment variables and , not web.config.
  • That is what let our BMW FS services move to Linux . A Linux plan is cheaper than a Windows one for the same size, and the same app runs in a Docker container for local tests. The cost line I'd mention: the move changed the hosting bill, not the business logic.
What goes wrong in a migration
  • Windows-only code compiles fine and fails on Linux at run time. For us it was , used to draw the logo on letters: Windows only since .NET 6. The compiler warned with CA1416, but the build had hundreds of warnings and nobody read them. That is the production incident further down.
  • The smaller ones: backslashes in file paths, file names in the wrong case (Linux file names are case-sensitive), and quietly returning null because ASP.NET Core never reads web.config. Both are in the bugs below.
How I choose
  • New services: the current LTS, so .NET 10 today, and we plan the upgrade before the old one's end date. .NET 8's support ends on 10 November 2026, so a team on .NET 8 has to move this year.
  • Old Framework code: I don't rewrite it all at once. If a host loads it, like the FIS core loads our plugins, it stays on 4.8. Shared logic moves to a library that targets both. A big web app moves route by route behind a proxy (a server that forwards each request to the old or the new app), the strangler fig pattern, so the old and new apps run side by side until the old one is empty.

Twenty-four years of .NET on one line

Time runs left to right. Each step adds the releases an interviewer expects you to place.

1/72002: .NET Framework 1.0. Windows only, part of Windows.

The story

  1. Before

    BMW FS dealers ask our payoff API what a customer owes to close a early. It was written in 2016 on .NET Framework, the original .NET, and ran inside IIS, the web server built into Windows, on a Windows App Service plan (the rented servers the apps share). Two other apps shared that plan, and all three used the one copy of Framework that Windows had.

    1/4Before: three apps on one Windows plan, all using the machine's one .NET Framework.

  2. Why it had to change

    Framework was built into Windows, so it could never leave Windows, and one shared copy meant every app moved together. Microsoft couldn't change that without breaking millions of apps, so it built a new .NET beside it instead.

  3. How it works now

    That new one is .NET Core, called just .NET from version 5. Its runtime (the engine that loads your compiled code and runs it) is not part of Windows: each app says which version it needs. Here is the path one app takes, from build to its first request:

    1/5The build compiles the code for the version in the project file: .NET 8.

In the lending API

The whole start-up of an ASP.NET Core app. On .NET Framework, IIS did all of this for you.

Only the key lines are shown; Deep walks the whole file.

Lending.sln · where this file sits
  • PayoffApi/
⋯ 2 lines in Deep⋯ 3 lines in Deep
Program.cs · line 2 · 1 of 3Program.cs is where the app starts; args are the values it was started with. This line prepares the app and reads settings from appsettings.json and environment variables. It does not start the server yet.

The code, file by file

The BMW FS API after the move: the old web.config line it replaced, its project file and its Program.cs. Tap Next to walk the diagram with the code.

Lending.sln · where these 3 files sit
  • PayoffApi/
Diagram · step 1Before: the API runs inside IIS on Windows, on the one .NET Framework the machine has.
Before · Web.config · line 2 · 1 of 2The old settings file. On Framework, IIS and read it. ASP.NET Core never reads it.

What they ask next

The follow-ups interviews really ask. Answer out loud, then tap to check.

Follow-up tree

Answer, then open the next level. That is the order an interviewer digs in.

Reporteda candidate was asked Intervieweran interviewer asks it

Production bugs, and how to tell them

Each one: what you see, why, the fix in code, and the line to say.

Production incident: Payoff letters failed after the move to Linux

P2 · serious, has a workaroundBMW FScame with a deployPayoff API and letter service, moved from .NET Framework 4.8 to .NET 8

Composed, not a real event at BMW FS. The mechanism is real: since .NET 6, `System.Drawing.Common` works only on Windows; on Linux its first use throws `TypeInitializationException` with `PlatformNotSupportedException` inside (Microsoft Learn breaking-change note), and the compiler only warns, with CA1416 (checked with a build on .NET 10). Times, counts, names, ticket and PR numbers are composed.

The story in 5 lines
  1. On Tue 6 May 2025, the day after the API went live on .NET 8 on a Linux plan, every letter request failed. Payoff amounts on screen still worked, so dealers saw only "letter could not be created".
  2. moved letter traffic back to the old Windows app, which was still running as a fallback, within 50 minutes.
  3. The letter code drew the BMW FS logo and a barcode with . Since .NET 6 that library works only on Windows. On Linux, the first use throws .
  4. The compiler had warned (CA1416, 6 times), but the build already had about 800 warnings, and dev laptops and the test environment were Windows, so nothing failed before production.
  5. The fix replaced the drawing code with SkiaSharp, a cross-platform library, made CA1416 an error, and moved the test environment to Linux.
Who's who (4 people)
You
.NET developer on the vendor team. Did the migration, finds the cause, writes the fix.
Tech lead
Vendor senior. Approved the move to Linux, reviews the fix, runs the postmortem.
L2 pod
Vendor support. First look at alerts, runs log queries, flips the fallback setting.
BMW FS payoff ops lead
Owns the payoff letters customers receive. Decides what customers are told.

Tap a step. The map lights the place where it happens.

1/8 Detect

Detect: 100% of letter requests fail on the new Linux app. Payoff amounts still work.

Tue 6 May 2025, 08:40 CT (19:10 IST)Azure Monitor alert, then the L2 pod

  • What: an fires on the new API: the failure rate on POST /letters/payoff is 100%. Times are US Central (CT), where BMW FS's US teams work. Dealers call BMW FS: "the amount shows, but the letter button says it could not be created".
  • Why it hid: the move to Linux went live the evening before, after business hours. The after release called the amount, not the letter.
  • How we saw it: ran the query below in , the query language of (Azure's store for the app's logs and errors). Every failure was the same exception, from one endpoint.
App Insights: failures by endpoint and type
exceptions
| where timestamp > ago(2h)
| where cloud_RoleName == "payoff-api"
| summarize count()
    by operation_Name, type
| order by count_ desc
Try it yourself · 10 minutes, on your Mac
  1. dotnet new console -n DrawLab, then dotnet add package System.Drawing.Common --version 8.0.10 (the version a .NET 8 app used; newer versions show a different inner error).
  2. In Program.cs: new System.Drawing.Bitmap(1, 1); inside a try / catch that prints the exception's type.
  3. dotnet build: read warning CA1416. dotnet run: , because a Mac is not Windows.
  4. Add <WarningsAsErrors>CA1416</WarningsAsErrors> to the project file and build again: now it fails before it can run.
You should see

Windows-only code compiles everywhere and fails at run time off Windows. The warning is the only early sign.

The senior move

"Moving to .NET 8 is about the OS as much as the version: we test on Linux, and a Windows-only call breaks the build, not production."

Sources Sourced: System.Drawing.Common is Windows only from .NET 6 and throws TypeInitializationException with PlatformNotSupportedException on other platforms (Microsoft Learn, breaking change "System.Drawing.Common only supported on Windows"; SkiaSharp is on its list of replacements); CA1416 warning checked with a build on .NET 10. Composed: BMW FS's systems, dates, counts, names, ticket and numbers, the setting name and the (standard columns).

Traps

Traps

What should you say instead? Tap to check.

Live coding

Easy first, then harder. Set a timer and type it before you look.

Task 1

Question index: Musteasy · 10 minutes

One class library must be used by a .NET Framework 4.8 plugin and by a .NET 8 API. Set up the project so one build produces both, and write a test that proves the rule gives the same answer.

Closest report, LTM: how do you write platform-independent code?
Stuck? Hints
  1. One project file can name more than one target framework. Which element is plural?
  2. Which code can you not use if one of the targets is Framework 4.8?
Show a solution
Lending.sln · where these 2 files sit
  • tests/Udc.Arrears.Tests/
Udc.Arrears.Tests.csproj · line 2 · 1 of 2Same two targets as the library, so each test runs against each DLL.
What the interviewer checks
  • (plural) with net48;net8.0.
  • Knows the build output has one folder per target.
  • Can name .NET Standard 2.0 as the other way, and when he'd pick it.
  • Senior extra: says the tests should run for both targets too.

Task 2

Question index: Mustmedium · 20 minutes

You are given a .NET Framework Web API 2 controller that reads and builds its own with . Port it to an ASP.NET Core controller on .NET 8.

Closest report, HCLTech: how does .NET Core differ from .NET Framework?
You are given

The old controller, as it was on .NET Framework. Here is handed the URL; after the port it reads itself, as in the second bug above.

Lending.sln · where this file sits
  • Controllers/
Stuck? Hints
  1. What does an ASP.NET Core controller inherit from, and how does it mark its route?
  2. Who should build the now?
  3. Where does the URL live after the move?
Show a solution
Lending.sln · where these 2 files sit
  • Controllers/
Diagram · step 1At start-up, Program.cs registers . The container builds it when first needed.
Program.cs · line 2 · 1 of 1Registers . The container will build it and give it .
What the interviewer checks
  • with [ApiController] and a route attribute.
  • registered in Program.cs and received in the constructor, not built with .
  • The URL in appsettings.json, read through when is built.
  • Returns / Ok(...).
  • Senior extra: mentions so connections are reused.
With AI tools

Interviewers now ask how AI tools help with migrations. Microsoft's own answer is the GitHub Copilot modernization agent in Visual Studio, which replaced the deprecated .NET Upgrade Assistant (the deprecation is recent, 2026): it scans a Framework solution, plans the upgrade, and fixes project files and common APIs. I'd use it for that mechanical part and still check three things it is weak on: Windows-only calls that compile and fail on Linux (I turn CA1416 into an error), settings that used to come from web.config, and anything the host process loads. And I ask an assistant for support dates only with a link to Microsoft's support page, because old answers still say STS is 18 months.

Glossary: every name, one line each →

My notes

Paste the NOTES block from your doubt chat here. The grader never reads notes; the coach reads "Still unclear".

Read moreWhere it was asked