With the release of .NET Core 2.0 and .NET Standard 2.0, now is a great time to consider upgrading your projects to .NET Core and your libraries to .NET Standard.

By upgrading your projects to .NET Core 2.0 you get cross-platform support and higher performance. By upgrading your libraries to .NET Standard you get greater compatibility and ensure they can be used in projects targeting either .NET Core or .NET Framework.

In this post, I summarize the features of .NET Framework and .NET Core, explain why the 2.0 releases make it so much easier to upgrade than earlier releases, and give you processes, tips, and tools to simplify the upgrade.

Understanding the Frameworks / Platforms

.NET Core and .NET Framework are both platforms and frameworks. The platform part refers to the runtime and compiler, while the framework part refers to the code library. For a more detailed explanation, read my previous post that investigates whether .NET is a framework or a platform.

.NET Framework

.NET Framework is the traditional full framework that you've been using for years. Microsoft released .NET Framework 1.0 in 2002!

You're probably using .NET Framework 4.6.1, the most popular version at present, or .NET Framework 4.7, the latest release at present.

It has these features:

  • Runs on Windows
  • Installed as part of the OS
    • All applications on a single computer run on the same .NET Framework version
  • High Compatibility
    • Compatible with the widest range of NuGet packages, third-party libraries, and internal libraries
  • v4.6.1+ implements .NET Standard 2.0

.NET Core

.NET Core is newer and features many improvements over .NET Framework. Microsoft released .NET Core 1.0 in June 2016, a little over a year ago, and just released .NET Core 2.0.

If you started a new project in the last 12 months, particularly an ASP.NET Core project, you may be using .NET Core.

It has these features:

  • Cross-platform (the OS kind of platform)
    • It runs on Windows, Linux, and macOS
  • Installation is standalone and side-by-side
    • You can run different versions of .NET Core for different applications on the same computer
  • High Performance
    • Improvements over .NET Framework in Collections, Math, Regex, Strings, Files, and more.
  • Open Source
    • Part of the .NET Foundation and generally licensed under either an MIT or Apache 2 license
  • v2.0 implements .NET Standard 2.0

Others

While you've probably heard of .NET Framework and .NET Core, these are not the only .NET platforms. There is also Mono, Xamarin.iOS, Xamarin.Mac, Xamarin.Android, and others; plus, there may be new platforms in the future.

This post focuses on .NET Framework and .NET Core, but the discussions about .NET Standard apply to these other platforms as well. In fact, .NET Standard 2.0 is implemented by Mono 5.4, Xamarin.iOS 10.14, Xamarin.Mac 3.8, and Xamarin.Android 7.5, in addition to .NET Framework 4.6.1+ and .NET Core 2.0.

Why Upgrade Now?

.NET Standard 2.0 and .NET Core 2.0 add new APIs and a compatibility mode that make it much easier to upgrade.

Support for Missing APIs

.NET Standard 2.0 and .NET Core 2.0 more than double the number of available APIs from .NET Standard 1.6, going from 13,000 to 32,000 APIs. So, it is now much easier to upgrade.

Previously, the challenge with upgrading to .NET Core was that many existing .NET Framework projects were using APIs that simply did not exist in .NET Core. For example, SmtpClient in System.Net.Mail.

With .NET Standard 2.0 support, .NET Core 2.0 now supports many of these missing APIs. And for the APIs that are not supported, for example, System.Drawing, there are now good alternatives such as ImageSharp.

Compatibility Mode

.NET Standard 2.0 also adds a new compatibility mode that allows projects to target .NET Framework libraries, provided the libraries only use APIs in .NET Standard 2.0. This enables usage of many older .NET Framework libraries that were previously unusable in .NET Core projects and .NET Standard libraries.

Approximately 70% of NuGet packages targeting .NET Framework can be targeted under compatibility mode. Previously, any projects or libraries that had dependencies of these packages could not be upgraded.

Installation of .NET Core 2.0

The first step is to upgrade to Visual Studio 2017.3. Once you've done that, you then need to download and install the .NET Core 2.0 SDK. Unfortunately, this SDK does not come preinstalled with the Visual Studio 2017 update.

At this point, you should be able to create new projects targeting .NET Core 2.0 and .NET Standard 2.0.

Create New Project

You might notice the framework version drop down at the top of the new project dialog box. This drop down only contains different versions of .NET Framework. Do not worry, ignore this drop down and select the desired project type. It will select the newest framework of the correct type.

You can confirm the correct type has been selected after creating your new project. Right click on the project in solution explorer, select properties, and go to the application tab. You will see that the correct framework is selected in target framework. If you want to target a different version, for example, an older version of .NET Standard for a library, you change that here.

Change Target Framework

Upgrading Existing Projects and Libraries

Upgrade Candidates

Not all projects are candidates for an upgrade to .NET Core 2.0 or .NET Standard 2.0.

Great Candidates

Console and ASP.NET Core projects are the easiest to upgrade and both make great candidates.

With ASP.NET Core projects, you'll want to upgrade them to ASP.NET Core 2.0 before switching to .NET Core. Because ASP.NET Core 2.0 targets .NET Standard 2.0, it supports more APIs and will be easier to migrate to .NET Core.

Good Candidates

ASP.NET MVC and ASP.NET Web Api are good candidates, but require a little more work.

With both ASP.NET MVC and ASP.NET Web Api, you'll need to start by upgrading them to ASP.NET Core. This is a challenge, but still achievable due to the similarities between them and ASP.NET Core. You can then continue to upgrade them as per ASP.NET Core.

Non-Candidates

Projects using ASP.NET Web Forms, Windows Communication Foundation (WCF), Windows Workflow Foundation (WWF), Windows Presentation Foundation (WPF), or Windows Forms are bad candidates. You should not attempt to upgrade them to .NET Core.

With ASP.NET Web Forms projects, a migration to .NET Core is going to involve a total rewrite in ASP.NET Core. Therefore, it is prudent to classify these as legacy projects at this point.

For projects built on Windows only and .NET Framework only technologies such as WCF, WWF, WPF, and Windows Forms, you'll need to stick with .NET Framework. These projects cannot be converted to .NET Core and should continue to target .NET Framework due to their dependencies.

Libraries

For libraries, use their consumers as a guide.

If they're consumed by projects that you're upgrading to .NET Core, upgrade them to .NET Standard or .NET Core if absolutely necessary.

If they're consumed by multiple projects, some of which are being upgraded and others which are not, then upgrade them to .NET Standard; upgrading will enable you to reference these libraries from both the upgraded .NET Core projects and the non-upgraded .NET Framework projects.

If they're only consumed by non-upgradeable projects, optionally upgrade them to .NET Standard; this would be beneficial if you intend to use them in newer projects in the future.

For libraries that build on .NET Framework technologies like Windows Forms, they'll need to remain on .NET Framework.

Upgrade Process

Start by upgrading your libraries to .NET Standard. You'll be able to continue using them from all your current projects, whether they target .NET Core or .NET Framework.

The next step is to upgrade your projects to use frameworks that are compatible with .NET Core. If you're using ASP.NET MVC or ASP.NET Web Api, this involves migrating to ASP.NET Core. If you're already on ASP.NET Core, but targeting .NET Framework, upgrade to ASP.NET Core 2.0 first (it supports .NET Framework).

The last step is to upgrade your projects to use .NET Core. If you're using APIs that are unsupported, you will need to migrate to an alternative. In some cases, this will be a different, newer API, which is already part of .NET Core. In other cases, you'll need to use an external library that adds the missing functionality.

If you're using libraries that don't support .NET Core, you'll either need to upgrade them, find replacements, or use them in compatibility mode.

Migration

To migrate your projects over to .NET Core 2.0 and .NET Standard 2.0, you have two options:

  1. Create a new project and copy over code.
  2. Convert your existing project by editing the csproj file.

For the second option, there are two steps:

  1. Migrate to the new project format using the manual approach outlined by Nate McMaster.
  2. Switch from .NET Framework to .NET Core or .NET Standard.
    • Edit csproj and change the TargetFramework tag from a .NET Framework version like net461 to either netcoreapp2.0 for .NET Core 2.0 or netstandard2.0 for .NET Standard 2.0.

.NET Portability Analyzer

To work out if you can upgrade from .NET Framework to .NET Core and to find what you need to change, use the .NET Portability Analyzer extension for Visual Studio.

This is a fantastic tool that scans your projects and checks all the APIs being used against the configured framework targets. It can identify which APIs are being used that are incompatible with a given target and even suggests newer alternative APIs in some cases. In my experience, the suggestions are quite rare, so you'll be on your own in most cases.

Once you have installed the .NET Portability Analyzer. Go to the Analyze menu, and select Portability Analyzer Settings to configure the options. You can set the output directory, select the output formats (Json, HTML, Excel), and the target platforms.

.NET Portability Analyzer Settings

The next step is to run the analyzer. The best way to do this is to right click on the project or solution to analyze. Selecting the solution will run the analyzer on all projects. Once you have run the analyzer, you can view the reports.

In the following report snippet, you can see that System.Web.HttpCachePolicyBase is only supported by .NET Framework. Whereas System.Configuration.ConfigurationManager is supported in .NET Core and .NET Framework, but not .NET Standard. The report also provides a suggestion as to how you might resolve the issue with ConfigurationManager in a .NET Standard project. In this case, the project is an ASP.NET MVC project; once it is migrated to ASP.NET Core, everything should be supported by .NET Core.

.NET Portability Analyzer Results

Upgrade Issues

.NET Standard, Old-Style Project, and Transitive Dependencies

If you try to reference a .NET Standard package from an old-style csproj project, and it contains transitive dependencies, you might get a runtime error that looks like this:

Could not load file or assembly '[...]' or one of its dependencies. The system cannot find the file specified.

A transitive dependency is when your project depends on a package, that itself depends on another package. The problem manifests itself as not being able to find that final package.

The problem occurs because the old-style csproj projects are setup by default to use Packages.config for package management. The new-style csproj projects use the newer PackageReference format. The newer format handles transitive dependencies correctly.

Solution #1: Upgrade to a New-Style Project

.NET Core and .NET Standard use the new csproj project format. However, at this stage, everything else uses the old-style csproj project format. That includes all your .NET Framework projects and other project types such as Xamarin.

For some .NET Framework projects, it is possible to upgrade to the new csproj format; you do this as described earlier in the migration section. However, this only works for ASP.NET Core, Console, and Class Library projects. For others, such as Xamarin, it doesn't currently work.

Hopefully, the new csproj format will be supported by more project types in the future. There is a User Voice suggestion where you can vote to add that support.

Solution #2: Switch from Packages.config to PackageReference

For projects that cannot be upgraded to the new csproj format, Scott Hanselman has the solution: you need to change the package management system by changing the RestoreProjectStyle property.

You change the RestoreProjectStyle property as follows:

  1. Unload the project.
  2. Edit the project's csproj.
  3. Set the RestoreProjectStyle to PackageReference in the first <PropertyGroup>.
  4. Reload the project.

Steps 1, 2, and 4 are completed by right clicking on the project in solution explorer. After step 3, the first <PropertyGroup> will look like this:

<PropertyGroup>
  [... other properties ...]
  <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>

Other Issues

Have you run into an issue while upgrading to .NET Core or .NET Standard?

Please post about it in the comments below. Another reader might know the solution.

And if you've already solved it, please post that too along with your workaround or solution.

Conclusion

If your project is a good candidate for upgrading to .NET Core and you've delayed upgrading due to missing APIs, now is a good time to recheck. The APIs or a good alternative might be available.

If you have put off upgrading your libraries to .NET Standard 2.0 due to a dependency not supporting .NET Standard, now is a good time to recheck. The dependency might now work with .NET Standard 2.0 due to the new compatibility mode.

To check for compatibility and to ease migration of existing projects and libraries, use the .NET Portability Analyzer extension for Visual Studio.

Post your upgrade issues and success stories in the comments below.