.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
.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.
Make it yours · 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.
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 repoExample 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
Payoff quote requestBMW FS dealer portal
Windows serverIIS
Payoff APIbuilt for 4.8
Two other appsalso on 4.8
.NET Framework 4.8one per machine
1/7Before: the API runs inside IIS on Windows, on the one .NET Framework the machine has.Windows updates Framework in place: all three apps change at once. And it can't run on Linux.Fix: rebuild for .NET 8. The project file (the app's build settings) names the version it needs.On Linux, the .NET 8 runtime starts the app. Program.cs sets it up, then starts Kestrel.A dealer asks for a . Kestrel takes the request and hands it to the app's code.Side by side: the next app is on .NET 10 on the same plan. Neither one changes the other.Framework: one shared copy, Windows only. .NET: each app picks its version, and runs anywhere.
In plain words
.NET is what runs C# code: a runtime (the engine that loads your compiled code and runs it, manages memory and catches errors) plus a large class library (ready-made code for files, dates, web requests and so on). The next card, CLR and JIT, opens the engine up.
.NET Framework is the first one, from 2002. It only runs on Windows and is part of Windows. A machine has only one 4.x version, and every app built for 4.x shares it. When Windows updates it, every app gets the new version at the same moment: an in-place update. Its latest version is 4.8.1 (2022), and Microsoft plans no new features.
.NET Core came in 2016. Microsoft rebuilt the runtime to be cross-platform (it runs on Windows, Linux and macOS) and open source (the code is public on GitHub). Each app says which version it needs, so different versions sit side by side on one machine. An app can even carry its own copy of the runtime: self-contained.
.NET 5 and later: at version 5 Microsoft dropped the word "Core" and skipped the number 4, so it wouldn't be mixed up with Framework 4.8. .NET 5, 6, 7, 8, 9, 10 are all the same line as .NET Core, just newer.
LTS and STS: a new .NET comes out every November. Even numbers (8, 10) are LTS, Long Term Support: free fixes for 3 years. Odd numbers (9) are STS, Standard Term Support: 2 years. Companies usually run LTS.
ASP.NET Core is the web part (APIs and web pages) of .NET Core and .NET 5+. Old ASP.NET (MVC and Web Forms pages) ran inside IIS, Windows' web server. ASP.NET Core has its own small web server, Kestrel, so the same app can run on Linux or in a Docker container (an app packed with everything it needs to run, so it runs the same anywhere).
Settings: old Framework apps kept settings (like a server address) in a file called web.config. ASP.NET Core reads appsettings.json instead, plus environment variables (values the server sets for the app, so each environment can differ).
Left behind: a few Framework parts never moved to .NET Core: Web Forms (drag-and-drop web pages) and the server side of WCF (Framework's toolkit for services that talk in SOAP, an older XML message format). Apps using them must be rewritten to move.
Plugin and host: the FIS Asset Finance core is a .NET Framework program. Our plugins are DLLs (files of compiled code) that FIS loads into its own process, so they must be built for Framework too. Our own Azure services are separate apps, so they can use .NET 8.
Target framework: the line in a project file that says which .NET the code is built for, written as a short code (a TFM):net48 is Framework 4.8, net8.0 is .NET 8. A library can list two and be built for both.
Which to use: new code on the newest LTS. Keep Framework only where something forces it, like a Windows-only host that loads your code.
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.
year 2000 → 2027
.NET Framework
.NET Core
.NET 5 and later
1.0
250 ms
1/72002: .NET Framework 1.0. Windows only, part of Windows.2005 to 2019: 2.0, 3.5, then 4.0 to 4.8. Each 4.x replaces the one before on the machine.2016: .NET Core 1.0 starts beside it: cross-platform and open source.2017 to 2019: Core 2.0, then 3.0 (WPF, WinForms) and 3.1, the last called Core.2020: .NET 5. "Core" dropped, 4 skipped. The Core line goes on under one name.2021: .NET 6 (LTS); phones joined through MAUI in 2022. 2022: Framework 4.8.1, the latest.Every November since: 8 (LTS, 2023), 9 (STS), 10 (LTS, 2025). 8 and 9 end Nov 2026.
The story
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.
Payoff APIFramework 4.8
Statements appFramework 4.8
Dealer adminFramework 4.8
.NET Frameworkone copy, part of Windows
1/4Before: three apps on one Windows plan, all using the machine's one .NET Framework.Framework 4.x on the server is updated in place. All three apps change on the same night.Architects want cheaper Linux plans and Docker (an app packed to run anywhere). Framework can't.Fix: move the API to .NET 8. It names its own version and runs on Linux.
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.
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:
Builddotnet publish
Linux serverApp Service
.NET 8runtime
Payoff APIwith Kestrel
build for net8.0
1/5The build compiles the code for the version in the project file: .NET 8.The deploy job copies the app's compiled files (DLLs) to the Linux server. No Windows, no IIS.The server starts the .NET 8 runtime the app asked for, not whatever happens to be newest.The runtime loads the app. The app starts Kestrel, its own web server.A dealer's request arrives. Kestrel passes it to the code, and the answer goes back.
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.
Payoff quote requestBMW FS dealer portal
Windows serverIIS
Payoff APIbuilt for 4.8
Two other appsalso on 4.8
.NET Framework 4.8one per machine
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.
ReportedWhat platforms does .NET 5 and later support?
Windows, Linux and macOS for servers and desktop tools, mainly on x64 and Arm64 processors (the two common chip families in servers and laptops). Web apps and APIs run anywhere, including Docker containers and Linux . Desktop UI with WPF and WinForms is still Windows only. Phones (Android, iOS) came with .NET MAUI, Microsoft's app toolkit for phones and desktops, released in May 2022 on .NET 6; and the browser through Blazor WebAssembly, which runs C# inside the web page.
ReportedWhy did Microsoft drop "Core" and skip version 4?
To say there is now one .NET going forward. After .NET Core 3.1 came .NET 5, not 4, so nobody would mix it up with .NET Framework 4.x. Framework didn't merge into it: Framework stopped at 4.8.1 and stays as it is. .NET 5 was the next .NET Core, and from .NET 6 the mobile side (Xamarin, the old phone toolkit, now .NET MAUI) joined the same platform.
Your FIS plugins are on .NET Framework. Should we migrate them?
Not while the FIS core is a Framework host: it loads the plugin into its own process, so the plugin must be Framework too. Framework 4.8.1 is supported as long as the Windows it ships with, so staying is safe. What I'd do is move the shared logic into a library that targets both net48 and net8.0, so new .NET 8 services use the same code, and keep the plugin itself thin. Migration starts when the host changes, or when we need Linux or new C#.
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
ReportedWhat platforms does .NET 5 and later support?
Windows, Linux and macOS for servers and desktop tools, mainly on x64 and Arm64 processors (the two common chip families in servers and laptops). Web apps and APIs run anywhere, including Docker containers and Linux . Desktop UI with WPF and WinForms is still Windows only. Phones (Android, iOS) came with .NET MAUI, Microsoft's app toolkit for phones and desktops, released in May 2022 on .NET 6; and the browser through Blazor WebAssembly, which runs C# inside the web page.
ReportedWhy did Microsoft drop "Core" and skip version 4?
To say there is now one .NET going forward. After .NET Core 3.1 came .NET 5, not 4, so nobody would mix it up with .NET Framework 4.x. Framework didn't merge into it: Framework stopped at 4.8.1 and stays as it is. .NET 5 was the next .NET Core, and from .NET 6 the mobile side (Xamarin, the old phone toolkit, now .NET MAUI) joined the same platform.
Your FIS plugins are on .NET Framework. Should we migrate them?
Not while the FIS core is a Framework host: it loads the plugin into its own process, so the plugin must be Framework too. Framework 4.8.1 is supported as long as the Windows it ships with, so staying is safe. What I'd do is move the shared logic into a library that targets both net48 and net8.0, so new .NET 8 services use the same code, and keep the plugin itself thin. Migration starts when the host changes, or when we need Linux or new C#.
And a big ASP.NET Framework web app?
Piece by piece, never one big rewrite. A new ASP.NET Core app goes in front as a proxy, a server that forwards each request (Microsoft's YARP library, short for Yet Another Reverse Proxy, does this). Routes move to it one at a time; anything not moved yet is passed through to the old app. When the old app has no routes left, it is switched off. This is the strangler fig pattern. Microsoft's .NET Upgrade Assistant helped with project files; it is now deprecated, and Microsoft points to the GitHub Copilot modernization agent in Visual Studio instead.
ReportedWhat is ASP.NET Core?
The web part of .NET: APIs, web pages and real-time apps. Compared with old ASP.NET it is cross-platform, it runs its own web server (Kestrel) instead of needing IIS, it has dependency injection and a built in, and it reads settings from appsettings.json and environment variables. ASP.NET Core 2.x could still run on .NET Framework; from 3.0 it runs only on .NET Core and .NET 5+.
InterviewerHow was dependency injection different on .NET Framework?
There was no container built in. Teams added a third-party container library, like Unity, Autofac or Ninject, and plugged it into ASP.NET through in MVC or Web API. Many older classes just called on what they needed. In ASP.NET Core the container is part of the framework: you register in Program.cs and it hands classes what they ask for in their constructor. The page shows how.
What is .NET Standard, and do you still need it?
A list of APIs that every .NET of its time promised to have, so one library could run on all of them. .NET Standard 2.0 is the useful one: .NET Framework 4.6.1 and later and .NET Core 2.0 and later can all load it (Microsoft recommends 4.7.2 or later on the Framework side). For new code that only runs on .NET 5+, target net8.0 or net10.0 directly; there will be no new .NET Standard. Use 2.0, or multi-targeting, only when Framework must load the library too.
LTS or STS for a production API?
LTS, almost always: 3 years of fixes instead of 2, and upgrades on our schedule. A new .NET comes every November; even numbers are LTS. Today that means .NET 10 (to November 2028). The trap this year: .NET 8 (LTS) and .NET 9 (STS) both lose support on 10 November 2026, so teams on either need to be on .NET 10 by then. I'd raise that as a ticket, not wait for the security team to find it.
ReportedWhat are the main components of .NET Framework?
Two: the CLR (Common Language Runtime), the engine that runs your code, and the class library (FCL, Framework Class Library), the ready-made code you call. On top sit the app models: ASP.NET, WinForms, WPF, WCF. .NET Core has the same two parts, rebuilt. How the CLR runs code (IL, JIT) is the next card.
Each one: what you see, why, the fix in code, and the line to say.
Letter templates not found on Linux
System.IO.FileNotFoundException:
Could not find file
'/home/site/wwwroot/Templates\payoff.html'.
Cause
The code built the path with a backslash, "Templates\\payoff.html". Windows reads a backslash as a folder separator. Linux uses /, so it looked for one file whose name contains a backslash. Linux file names are also case-sensitive: templates and Templates are two different folders.
Fix
Build paths with , which puts in the right separator for the machine, and start from , the folder the app runs from. Match the folder's case exactly. A test now runs in a Linux container in the pipeline.
Diagram · step 1Before: the path is written with a backslash. On Windows that means a folder.
Letter codeLetterService
Windowsseparator \
Linuxseparator /
Templates\payoff.html
found
Before · LetterService.cs · line 2 · 1 of 2\\ in a C# string is one backslash. Windows treats it as a folder break.
Say it
Code that worked for years on Windows broke on Linux because of a hard-coded backslash. We switched to and added a Linux run to , so the next one fails the build, not production.
FIS URL is null after the move
System.ArgumentNullException:
Value cannot be null. (Parameter 'uriString')
at System.Uri..ctor(String uriString)
at FisClient..ctor()
Cause
The old code read the FIS address with , which on Framework read web.config. It still compiles on .NET 8, because Microsoft ships the old class as a NuGet package (a downloadable library). But on .NET 8 it reads the app's own PayoffApi.dll.config file, which doesn't exist, never web.config. So the value is null, and new Uri(null) throws when the class is built.
Fix
Move the setting to appsettings.json (and to an setting per environment), and read it through , which ASP.NET Core fills at start-up and hands in by . A missing value throws with its name the first time is built; to stop the app at start-up instead, check the setting in Program.cs before app.Run().
Diagram · step 1Before: the client asks , the Framework-era settings reader.
FisClientneeds FIS URL
Old configFramework era
New configappsettings
AppSettings["FisBaseUrl"]
Before · FisClient.cs · line 6 · 1 of 2On Framework this read web.config. On .NET 8 it reads PayoffApi.dll.config, which doesn't exist, so it returns null.
Say it
The migration compiled, so we thought config was fine, but was reading a file ASP.NET Core ignores. We moved settings to , and a missing value now throws with its name instead of a null error.
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
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".
moved letter traffic back to the old Windows app, which was still running as a fallback, within 50 minutes.
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 .
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.
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.
Payoff letter requestBMW FS dealer portal
App ConfigurationLetterServiceUrl
Linux plan.NET 8
Payoff APInew
System.DrawingWindows only
Letter requests: 412
Failed: 412 (100%)
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
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).
In Program.cs: new System.Drawing.Bitmap(1, 1); inside a try / catch that prints the exception's type.
dotnet build: read warning CA1416. dotnet run:, because a Mac is not Windows.
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."
SourcesSourced: 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
Don't say.NET Core is a lighter version of .NET Framework.SayIt is a separate rewrite: cross-platform, open source, side by side. .NET 5 and later continue it.
Don't say.NET 5 merged .NET Framework into .NET Core.SayFramework stopped at 4.8.1 and was not merged. .NET 5 is simply the next .NET Core, renamed.
Don't say.NET Framework is out of support.Say4.8.1 is supported with Windows and still gets security fixes. It just gets no new features.
Don't sayIf it compiles on .NET 8, it runs on Linux.SayWindows-only APIs like compile and fail at run time. Treat warning CA1416 as an error.
Traps
What should you say instead? Tap to check.
Don't say.NET Core is a lighter version of .NET Framework.
Say instead
It is a separate rewrite: cross-platform, open source, side by side. .NET 5 and later continue it.
Don't say.NET 5 merged .NET Framework into .NET Core.
Say instead
Framework stopped at 4.8.1 and was not merged. .NET 5 is simply the next .NET Core, renamed.
Don't say.NET Framework is out of support.
Say instead
4.8.1 is supported with Windows and still gets security fixes. It just gets no new features.
Don't sayIf it compiles on .NET 8, it runs on Linux.
Say instead
Windows-only APIs like compile and fail at run time. Treat warning CA1416 as an error.
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.
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
What does an ASP.NET Core controller inherit from, and how does it mark its route?
Who should build the now?
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.
RequestGET /payoff/…
Containerbuilds classes
PayoffControllerASP.NET Core
FisClientcalls FIS
FisClient registered
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.