Where did all the assemblies go ? .NET 5.0 error CS1069

Viewed 1460

So my code which worked fine yesterday, screwed up when I added a .net 5.0 class library project to my solution.

Error CS1069 The type name 'Bitmap' could not be found in the namespace 'System.Drawing'. This type has been forwarded to assembly 'System.Drawing.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.

There is just one problem, when i look at what replaced "References" it now says "Dependencies" and when I try to add a dependency, "Add reference" is gone and there are no more .net assemblies being shown except under COM projects and type libs and when I add system.drawing etc, the error still remains and the code remains unreadable.

2 Answers

There are multiple reasons for what you're experiencing, I'll try to explain with a variety of assorted (and unordered) bullet-points:

Why isn't System.Drawing in .NET Core?

  • ".NET 5" is the next iteration of .NET Core 3.1, not the .NET Framework 4.8 (.NET 5 comes immediately after .NET Core 3.1, there was never was a ".NET Core 4" to avoid confusion with .NET Framework 4).
  • .NET Core (including .NET 5) is designed to be cross-platform (i.e. to support Windows, Linux, macOS) with a single runtime.
    • Whereas previously people had to target .NET Framework for Windows, and target Mono, Xamarin, Unity, UWP, Silverlight, etc - which made multi-platform development in C# a pain.
    • Note that while Windows, Linux, and macOS now all share the real McCoy .NET 5 (and Silverlight is dead), other platforms like Xamarin, Unity, Mono, and UWP still have their own separate implementations of .NET (CLR+BCL) hence the need for ".NET Standard". At least we don't need those weird "Shared Projects" and "Portable Framework" projects anymore, phew!
  • In the .NET Framework, the System.Drawing API is just a .NET wrapper over Win32's GDI/GDI+, which means it's not cross-platform.
    • While System.Drawing seems like a platform-independent API, if you look closely at public types and methods like Graphics, Brush, Bitmap, Image and so on you'll see that they're all just thin wrappers and leaky-abstractions over GDI+. Mono does have System.Drawing reimplemented for Linux, however they did it by reimplementing GDIPLUS.dll which is about as horrible as it sounds.
  • So because System.Drawing is not cross-platform it was removed from .NET Core's "in-box" API.

So now you're wondering how you can get System.Drawing in .NET Core...

How can I get System.Drawing in .NET Core?

Earlier questions asked on StackOverflow from when .NET Core was more anaemic (and not yet pitched as a replacement for .NET Framework 4) have suggested switching to completely different and incompatible (but cross-platform-by-design) library, such as ImageSharp or ImageProcessor, however a better solution for Windows-only applications exists: the official Microsoft Windows Compatibility Pack (note that the aforementioned blog article is from 2017; as of 2021 the Windows Compatibility Pack is pretty-much fully implemented now).

All you need to do is open the NuGet package manager built-in to Visual Studio and add Microsoft.Windows.Compatibility as a package-reference and magically System.Drawing will be available for use in your application. You can also access the NuGet package manager via the Dependencies context-menu in Solution Explorer.

If you're using the .NET CLI ("command-line interface", not the "common language infrastructure", hurrah for overloaded acronyms) then just run dotnet add package Microsoft.Windows.Compatibility.

But why can't I add assembly references in .NET Core like I used to in .NET Framework?

You can!. It's just that (as of April 2021, running Visual Studio 2019 16.9) the UI for adding an assembly reference is kinda horrible.

  • You can do it manually by editing your .csproj and adding a <Reference Include="pathToDll.dll" /> (in the same <ItemGroup> as the other references).

  • You can do it from within Visual Studio by ignoring the missing menu option and using the Add Project Reference dialog:

    • Follow these steps

      1. Go Solution Explorer > Your Project > Dependencies > Add Project Reference.
        enter image description here
      2. In the popup dialog, choose the Browse tab:
        enter image description here
      3. Then click the Browse... button: enter image description here
      4. Then browse for your target assembly DLL:
      5. Voila - the added assembly reference will appear under a new Assemblies node under Dependencies:
        enter image description here
    • Do note that (generally speaking, there are exceptions) you can only reference assembly DLLs that target .NET Core or .NET Standard. Because most DLLs built for .NET Core and .NET Standard exist as NuGet packages anyway there isn't much need to add an assembly reference directly.

Microsoft seems to have migrated Add Reference to standard SDK assemblies to "Manage NuGet Packages".. a step I do not understand the point of since the correct assembly is mixed in with third party user contributed search results.

Simply click where references would have been and is now dependencies, and right-click and then click Manage Nuget Packages, do a search for the assembly and VERIFY that Microsoft published it and it meets the .net Core requirements.

Yeah they dropped the ball on this in my humble opinion. Took me a minute to figure out that standard assemblies do not appear to be installed on the system.

The package gets installed under your user account's home directory, not in a system-wide folder requiring elevated user permissions to access the dll, so if your account is bugged, you get to a nice infected copy of the assembly each and every time :)

Related