Portable- is dead, long live NetStandard

With the RC of NuGet 2.12 for VS 2012/2013, and imminent release of .NET Core on Monday the 27th, it’s time to bid farewell to our beloved/cursed PCL profiles. So long, you won’t be missed! Oh, and dotnet, please don’t let the door hit you on the way out either.

In its place we join the new world of the .NET Platform Standard and it’s new moniker netstandard.

When dotnet was released last July, there was a lot of confusion around what it is and how it worked. Working with the NuGet and CoreFX teams, I tried to explain it in a few of my previous posts. Despite good intentions, dotnet was a constant frustration to many library authors due to its design and limited support. dotnet only worked with NuGet v3, which meant that packages would need to ship a dotnet version and a version in a PCL directory like portable-net45+win8+wp8+wpa81 to support VS 2012/2013.

It was hard to fault anyone for wondering, “why bother?” The other downfall of dotnet, and likely the main one, was that dotnet fell into a mess trying to work with different compatibility levels of libraries. What if you wanted to have a version that worked with newer packages than were supported by Windows 8? What if you wanted to have multiple versions which “light up” based on platform capabilities? How many of you who installed a dotnet-based package, with its dependencies listed, saw a System.Runtime 4.0.10 entry and wondered why you were getting errors trying to update it? After all, NuGet showed an update to 4.0.20, why wouldn’t that work? The reality was that you had to release packages with multiple versions that were incompatible with some platforms because there was no way to put all of it into one package.

Enter .NET Platform Standard

netstandard fixes the short comings of dotnet by being versioned. As of today, there’s 1.0 – 1.6, with the following TFM’s netstandard1.0netstandard1.6. Now, the idea is that each .NET Platform Standard version supports a given set of platforms and when authoring a library, you’d ideally want to target the lowest one that has the features you need and runs on your desired target platform versions.

With NuGet 2.12, netstandard is also supported in VS 2012 and 2013, so that there’s no further need to include a portable-* version and a netstandard version in the same package. Finally!

What does this all mean

The short answer is that if you currently have a Profile 259 PCL today, you can change your NuGet package to put it in a netstandard1.0 directory and add the appropriate dependency group. The full list if profile -> netstandard mappings is here. If you support .NET 4.0 or Silverlight 5 in your PCL — basically a PCL “older” than 259, then you can continue to put that in your NuGet alongside the netstandard1.0+ version and things will continue to work. In addition, a platform-specific TFM (like net45) will always “win” over netstandard if compatible.

Detour: Dependencies for NetStandard

Like dotnet, netstandard requires listing package dependencies. For the most part, it’s easier than with dotnet as there is a meta-package, NETStandard.Library 1.6.0 (the RC2 version is 1.5.0-rc2-24027), that has most BCL dependencies included. This package is one that you probably have in your project.json today. Put the NETStandard.Library 1.6.0 dependency in a netstandard1.0 dependency group, along with any other top-level dependencies you have:

<dependencies>
  <group targetFramework="netstandard1.0">
    <dependency id="NETStandard.Library" version="1.6.0" />
    <dependency id="System.Linq.Queryable" version="4.0.1" />
  </group>
</dependencies>

Next steps

There’s about to be a lot to do over the coming weeks:

  • Get the .NET Core 1.0 RTM with the Preview 2 tooling
  • Download VS 2015 Update 3 when available
  • Grab NuGet 2.12 for VS 2012/2013

Start updating your packages to support .NET Core if you haven’t already. If you’ve been waiting for .NET Core RTM, that time has finally come. You can either use a csproj-based portable library targeting netstandard or use xproj with project.json. As an aside, my personal opinion is that xproj‘s main advantage over csproj today is cross-compiling. If you need to compile for multiple targets, that’s the currently the best option, otherwise, you’ll get a better experience using the csproj approach.

Converting existing PCL projects

VS 2015 Update 3 has a new feature that makes it easy to convert a PCL to netstandard. If your library has any NuGet dependencies installed, you need to first follow the steps to switch packages.config to project.json. Once you do that, you can select Target .NET Platform Standard from the project properties and it’ll convert it over:
Project Properties

Icing on the cake

Xamarin supports all versions of netstandard as well. This means that if you were cross-compiling because PCL 259 was too limiting, try taking another look at netstandard1.3+. There’s a lot more surface area there and it may mean you can eliminate a few target platforms.

Bonus Round

If you want to use xproj for its cross-compiling features and also need to reference that library from a project type that doesn’t support csproj -> xproj references today (most of them, including UWP don’t work super-well), I’ve written up an explanation of how you can do this on StackOverflow.