Scott Hanselman

How to reference a .NET Core library in WinForms - Or, .NET Standard Explained

June 16, 2017 Comment on this post [13] Posted in DotNetCore
Sponsored By

I got an interesting email today. The author said "I have a problem consuming a .net core class library in a winforms project and can't seem to find a solution." This was interesting for a few reasons. First, it's solvable, second, it's common, and third, it's a good opportunity to clear a few things up with a good example.

To start, I emailed back with "precision questioning." I needed to assert my assumptions and get a few very specific details to make sure this was, in fact, possible. I said. "What library are you trying to use? What versions of each side (core and winforms)? What VS version?"

The answer was "I am working with VS2017. The class library is on NETCoreApp 1.1 and the app is a Winforms project on .NET Framework 4.6.2."

Cool! Let's solve it.

Referencing a .NET Core library from WinForms (running .NET Full Framework)

Before we parse this question. Let's level-set.

.NET is this big name. It's the name for the whole ecosystem, but it's overloaded in such a way that someone can say "I'm using .NET" and you only have a general idea of what that means. Are you using it on mobile? in docker? on windows?

Let's consider that ".NET" as a name is overloaded and note that there are a few "instances of .NET"

  • .NET (full) Framework - Ships with Windows. Runs ASP.NET, WPF, WinForms, and a TON of apps on Windows. Lots of businesses depend on it and have for a decade. Super powerful. Non-technical parent maybe downloads it if they want to run or a game.
  • .NET Core - Small, fast, open source, and cross-platform. Runs not only on Windows but also Mac and a dozen flavors of Linux.
  • Xamarin/Mono/Unity - The .NET that makes it possible to write apps in C# or F# and run them on everything from an iPad to cheap Android phone to a Nintendo Switch.

All of these runtimes are .NET. If you learn C# or F# or VB, you're a .NET Programmer. If you do a little research and google around you can write code for Windows, Mac, Linux, Xbox, Playstation, Raspberry Pi, Android, iOS, and on and on. You can run apps on Azure, GCP, AWS - anywhere.

What's .NET Standard?

.NET Standard isn't a runtime. It's not something you can install. It's not an "instance of .NET."  .NET Standard is an interface - a versioned list of APIs that you can call. Each newer version of .NET Standard adds more APIs but leaves older platforms/operating systems behind.

The runtimes then implement this standard. If someone comes out with a new .NET that runs on a device I've never heard of, BUT it "implements .NET Standard" then I just learned I can write code for it. I can even use my existing .NET Standard libraries. You can see the full spread of .NET Standard versions to supported runtimes in this table.

Now, you could target a runtime - a specific .NET - or you can be more flexible and target .NET Standard. Why lock yourself down to a single operating system or specific version of .NET? Why not target a list of APIs that are supported on a ton of platforms?

The person who emailed me wanted to "run a .NET Core Library on WinForms." Tease apart that statement. What they really want is to reuse code - a dll/library specifically.

When you make a new library in Visual Studio 2017 you get these choices. If you're making a brand new library that you might want to use in more than one place, you'll almost always want to choose .NET Standard.

.NET Standard isn't a runtime or a platform. It's not an operating system choice. .NET Standard is a bunch of APIs.

Pick .NET Standard

Next, check properties and decide what version of .NET Standard you need.

What version of .NET Standard?

The .NET Core docs are really quite good, and the API browser is awesome. You can find them at 

The API browser has all the .NET Standard APIs versioned. You can put the version in the URL if you like, or use this nice interface.

API Browser

You can check out .NET Standard 1.6, for example, and see all the namespaces and methods it supports. It works on Windows 10, .NET Framework 4.6.1 and more. If you need to make a library that works on Windows 8 or an older .NET Framework like 4.5, you'll need to choose a lower .NET Standard version. The table of supported platforms is here.

From the docs - When choosing a .NET Standard version, you should consider this trade-off:

  • The higher the version, the more APIs are available to you.
  • The lower the version, the more platforms implement it.

In general, we recommend you to target the lowest version of .NET Standard possible. The goal here is reuse. You can also check out the Portability Analyzer and run it on your existing libraries to see if the APIs you need are available.

.NET Portability Analyzer

.NET Standard is what you target for your libraries, and the apps that USE your library target a platform.

Diagram showing .NET Framework, Core, and Mono sitting on top the base of .NET Standard

I emailed them back briefly, "Try making the library netstandard instead."

They emailed back just a short email, "Yes! That did the trick!"

Sponsor: Big thanks to Raygun! Don't rely on your users to report the problems they experience. Automatically detect, diagnose and understand the root cause of errors, crashes and performance issues in your web and mobile apps. Learn more.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
June 16, 2017 11:46
Thank you, Scott.
Awesome explanation! I really like this clear statement ".NET Standard isn't a runtime or a platform. It's not an operating system choice. .NET Standard is a bunch of APIs." And the way you helped solve the problem, that is to find the real problem
""run a .NET Core Library on WinForms." Tease that apart that statement. What they really want is to reuse code - a dll/library specifically."
June 16, 2017 11:49
At least all of this isn't too complex and the UI in Visual Studio is always pretty much self explanatory. You couldn't even possibly do the wrong thing!

Now its time for me to get back to work and recreate a couple of libraries collegues created in the wrong project types/.Net version that won't run/compile/work in the stack we're actually using.
June 16, 2017 12:06
Thank you for writing another interesting post. I have a question about what actually happens when you create a .NET Standard Class Library. Since .NET Standard is only an interface, what is the actual implementation of .NET that is used when you create a .NET Standard Class Library? Is it just a version of .NET Core that exposes the required APIs?
June 16, 2017 13:32
Now that has cleared up a lot of misunderstandings in my head.
Thanks Scott.
June 16, 2017 17:00
How much did you charge them for the consultation?
June 16, 2017 19:34
Great explanation, Scott, thank you. I'm looking for some resources that explain how the new compat shims work, which - I think - allow a NETStandard library author to reference libraries/packages that haven't yet explicitly been targeted to NETStandard (but would otherwise meet the spec of the parent NETStandard library). Heard Immo Landwerth mention these at .NET Fringe, but a quick search didn't turn up much. Perhaps it's a feature of the 2.0 tooling and not yet fully documented? Or perhaps I can learn how to better google something with bing for myself.
June 19, 2017 13:40
If you run into problems getting your .NET Framework assembly to accept a .NET Standard library, this might help you out:

How Do You Reference a .NET Standard Library from a .NET Framework 4.5 Console Application in Visual Studio 2017?

June 19, 2017 17:09
How would you expand on this for unit tests? I usually have a DLL that contains my tests, and in my limited tinkering it seems like the unit test assembly can't be .NET standard... or maybe that's because ReSharper can't figure out the core 2.0 preview stuff yet...

And then there's the whole matter of targeting multiple frameworks.

Lots of variables in there: target framework for assembly under test, test assembly, and test runner. Maybe a part 2 in the future?
June 19, 2017 20:00
I did this recently when working on my final year project. Very nice article!
June 20, 2017 7:18
So, you cannot reference a .NET Core library in Winforms? There's a high percentage chance that I have missed the point here.
June 20, 2017 11:25
Maybe the customer has understood the brief answer ("Try making the library netstandard instead."), but I did not.
Which library, and how do you "make" it netstandard? They said they were developing WinForms app, not a library.
June 21, 2017 9:36
What I don't understand is that ASP.NET Core MVC libraries depend on Standard 1.6.

According to the .NET Standard version table, Standard 1.6 is not supported on Framework 4.6.1, however I can (thankfully) target an ASP.NET Core app to run on Framework 4.6.1. This allows me to pull in Framework 4.6.1 based libraries, for functionality that isn't supported in .NET Standard 1.4.

However, if I want to include NuGet package Microsoft.AspNetCore.Mvc.Core, I cannot import this in a Standard 1.4 library, because it depends on Standard 1.6. And I cannot upgrade to Standard 1.6, because I cannot reference a Standard 1.6 library form a host app that targets Framework 4.6.1.

Unfortunately that library includes a very important interface: IActionContextAccessor.

However, I can change the library to Framework 4.6.1, depend on the NuGet package becase it can also target Framework 4.5.1, and then reference that in the host app?

But in future, when 2.0 tooling is released (still in preview) then it's possible to refer to a Standard 1.6 library from a Framework 4.6.1 host application.
June 27, 2017 23:11
But what the point in targeting net standard for win forms application? This app won't work on another os anyway!

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.