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
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.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
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>
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
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
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
project.json. Once you do that, you can select Target .NET Platform Standard from the project properties and it'll convert it over:
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.
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
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.