In Part 1 I talked about how I got from a .NET Framework 2.0 project to a .NET Standard 1.3 project.
In this post, I'll write down what I did to publish a NuGet package for the library that can be used by all platforms that support .NET Standard 1.3.
Creating a NuGet package
What I just did was compile C# code to an Intermediate Language (IL) assembly. An assembly doing only things supported in .NET Standard 1.3.
So every platform that supports .NET Standard 1.3 should be able to load and run that same IL assembly. There is no need to build for various platforms.
What's needed is to make the dll available to others, using a NuGet package.
Microsoft offers the following guide: Create .NET Standard Packages in Visual Studio 2017. But I won't be following it.
In Visual Studio 2017, in the project properties, I have noticed a tab "Package" with the option to "Generate NuGet package on build":
In the past, I used nuget.exe from the command line to build my NuGet package. It would be really great to do this from Visual Studio directly.
Setting the following package variables:
- Package ID: FlacLibSharp
- Version: 3.0.0
- Authors: Aaron Lenoir
- Product: FlacLibSharp
- Description: A .NET library for reading and writing FLAC metadata.
- Copyright: Copyright 2017
- License URL: http://www.apache.org/licenses/LICENSE-2.0.txt
- Project URL: https://github.com/AaronLenoir/flaclibsharp
A rebuild results in a "FlacLibSharp.3.0.0.nupkg" file in the bin\Release folder.
Testing the NuGet package in .NET Core
To test, I add my new NuGet package to a folder that also contains the old 2.0.0 nuget package. Then add that folder to my NuGet package sources.
After that I try to install the package via NuGet in a new .NET Core (1.0) Console application, hoping it will pick up te latest version.
For test code, I'll just use the example code from my github repository. Then I run:
And I receive the following output (excluded some lines)
PM> Install-Package FlacLibSharp GET https://api.nuget.org/v3/registration3-gz/flaclibsharp/index.json Restoring packages for C:\Users\user\Documents\Programming\github\flaclibsharp\FlacLibSharp.Test.DotNetCore\FlacLibSharp.Test.DotNetCore.csproj... Installing FlacLibSharp 3.0.0. Installing NuGet package FlacLibSharp 3.0.0. Committing restore... Writing lock file to disk. Path: C:\Users\user\Documents\Programming\github\flaclibsharp\FlacLibSharp.Test.DotNetCore\obj\project.assets.json Restore completed in 736,12 ms for C:\Users\user\Documents\Programming\github\flaclibsharp\FlacLibSharp.Test.DotNetCore\FlacLibSharp.Test.DotNetCore.csproj. Successfully uninstalled 'Microsoft.NETCore.Platforms 1.0.2' from FlacLibSharp.Test.DotNetCore Successfully uninstalled 'Microsoft.NETCore.Targets 1.0.3' from FlacLibSharp.Test.DotNetCore Successfully uninstalled 'Microsoft.Win32.Primitives 4.0.1' from FlacLibSharp.Test.DotNetCore Successfully uninstalled 'NETStandard.Library 1.6.0' from FlacLibSharp.Test.DotNetCore ... Successfully uninstalled 'System.Xml.XDocument 4.0.11' from FlacLibSharp.Test.DotNetCore Successfully installed 'FlacLibSharp 3.0.0' to FlacLibSharp.Test.DotNetCore Successfully installed 'Microsoft.NETCore.Platforms 1.1.0' to FlacLibSharp.Test.DotNetCore Successfully installed 'Microsoft.NETCore.Targets 1.1.0' to FlacLibSharp.Test.DotNetCore Successfully installed 'Microsoft.Win32.Primitives 4.3.0' to FlacLibSharp.Test.DotNetCore Successfully installed 'NETStandard.Library 1.6.1' to FlacLibSharp.Test.DotNetCore ... Successfully installed 'System.Xml.XDocument 4.3.0' to FlacLibSharp.Test.DotNetCore Executing nuget actions took 667,21 ms
I'm not too sure why all this is happening. But now my .NET Core app compiles and sure enough it runs just as well:
Flac audio length in seconds: 38 Artist - Title: Ziggystar - Roland jx3p demo StreamInfo metadata block. Seektable metadata block. VorbisComment metadata block. Padding metadata block.
Testing the NuGet package in .NET Framework 4.5
I know my project works in .NET Framework 2.0. But .NET Standard 1.3 is only supported by .NET Framework 4.6.1 and higher. So will my .NET Standard Package be imported to a .NET Framework 4.5 project?
Install-Package FlacLibSharp leaves me with the following error:
Install-Package : Could not install package 'FlacLibSharp 3.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
So that won't work. I must specify in my NuGet package that I have files for a lower .NET Framework too. In a ".nuspec" file, which was used in the past instead of that Visual Studio screen, it was possible to specify this like so:
<?xml version="1.0"?> <package> <metadata> <id>FlacLibSharp</id> ... </metadata> <files> <file src="..\FlacLibSharp\bin\Release\FlacLibSharp.dll" target="lib\20" /> <file src="..\FlacLibSharp\bin\Release\FlacLibSharp.xml" target="lib\20" /> </files> </package>
However, in Visual Studio 2017, MSBuild is responsible for creating the NuGet package. We must open the .csproj file to see this configuration:
<PropertyGroup> <TargetFramework>netstandard1.3</TargetFramework> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> <PackageId>FlacLibSharp</PackageId> <Version>3.0.0</Version> <Authors>Aaron Lenoir</Authors> <Company /> <Product>FlacLibSharp</Product> <Description>A .NET library for reading and writing FLAC metadata.</Description> <Copyright>Copyright 2017</Copyright> <PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0.txt</PackageLicenseUrl> <PackageProjectUrl>https://github.com/AaronLenoir/flaclibsharp</PackageProjectUrl> <PackageReleaseNotes>* Support for .NET Standard 1.3 platforms</PackageReleaseNotes> <RepositoryUrl>https://github.com/AaronLenoir/flaclibsharp</RepositoryUrl> <PackageTags /> </PropertyGroup>
We can actually add target frameworks, by adding them separated by a semicolon.
So I tried the following, which did not work:
This yields the error:
Cannot infer TargetFrameworkIdentifier and/or TargetFrameworkVersion from TargetFramework='netstandard1.3'. They must be specified explicitly.
What I did wrong was that "TargetFramework" must be renamed to "TargetFrameworks":
Reloading the project now, I'm able to build.
In the project properties in Visual Studio, I can no longer see the Target Platform:
I assume support for these configurations will be added to the UI in the future.
Unzipping the generated NuGet package, in the lib folder I now have a net20 folder and a netstandard1.3 folder. Both with "FlacLibSharp.DotNetStandard.dll" and "FlacLibSharp.DotNetStandard.xml" inside. For the release, I will renamed these back to FlacLibSharp.dll.
Trying it again in my .NET 4.5 project, it now works:
PM> Install-Package FlacLibSharp Attempting to gather dependency information for package 'FlacLibSharp.3.0.0' with respect to project 'FlacLibSharp.Sandbox', targeting '.NETFramework,Version=v4.5' Gathering dependency information took 0,59 ms Attempting to resolve dependencies for package 'FlacLibSharp.3.0.0' with DependencyBehavior 'Lowest' Resolving dependency information took 0 ms Resolving actions to install package 'FlacLibSharp.3.0.0' Resolved actions to install package 'FlacLibSharp.3.0.0' Retrieving package 'FlacLibSharp 3.0.0' from 'Package source'. Adding package 'FlacLibSharp.3.0.0' to folder 'C:\Users\user\Documents\Programming\github\flaclibsharp\FlacLibSharp\packages' Added package 'FlacLibSharp.3.0.0' to folder 'C:\Users\user\Documents\Programming\github\flaclibsharp\FlacLibSharp\packages' Added package 'FlacLibSharp.3.0.0' to 'packages.config' Successfully installed 'FlacLibSharp 3.0.0' to FlacLibSharp.Sandbox
And running the application works fine too.
I now have two projects, with the same source code. One old class library that targets .NET Framework 2.0 and one that targets both .NET Standard 3.0 and .NET Framework 2.0.
It makes sense to remove the old project and replace it with the new one. No need to share code over projects.
You only need 1 project for your library to build for all platforms that support your target .NET Standard version
Namespaces and assembly names
I have an assembly named "FlacLibSharp.DotNetStandard.dll", but it would better be called FlacLibSharp.dll, as in the past. Since it's really not a very different assembly.
Additionally, I shouldn't have the namespace refer to DotNetStandard either. Because that is pointless.
After doing these things, I was able to release my library for .NET Standard 3.0 and higher:
Creating a NuGet package is supported in Visual Studio 2017, but not all features are yet available in the GUI (Graphical User Interface).
If you want to use the library in older .NET Framework version that don't really support your .NET Standard, you must add them to the .csproj file manually.
You can have a single project for the library to target multiple platforms. No need to have projects for each platform you want to support.