Xamarin Forms PCL to .NET Standard Upgrade - Seeing All NuGet Packages? - xamarin.forms

I have a Xamarin Forms app which was built with PCL.
When installing NuGet packages I would see all packages installed in NuGet Explorer.
Example Android Project:
Xam.Plugin.Geolocator **5.0.0.187-beta**
It might rely on the following NuGets:
However, when I install Xam.Plugin.Geolocator in the .NET Standard 2.0 solution I don't see the other plugins in the Nuget Package Explorer like I did in PCL project.
Regardless, the Forms App works just fine. Why don't the dependency package show up anymore? How can I know what version of the dependency packages I have installed?
I've gone ahead and manually installed them to the .NET Standard project, but that doesn't feel correct...
Additionally, I've noticed there is no longer a Packages folder in any of my Projects.
In my PCL Solution, I could see the dependencies. See Below:

There should be a Dependencies - NuGet folder for a .NET Standard SDK style project. There is no Packages folder for an SDK style project.
You can expand the Dependencies - NuGet folder items to see the dependencies. If there are no child nodes then there are no dependencies.
You can also see more detailed information in the project.assets.json file which is created in the obj directory after restoring the NuGet packages.
Xam.Plugin.Geolocator has just the .NET Standard.Library NuGet package as a dependency if you are installing it into a .NET Standard project. This NuGet package would be referenced by default in a .NET Standard project. When I install that into a .NET Standard 2.0 project in Visual Studio 2017 it shows no dependencies.
The full set of dependencies taken from the .nuspec file is:
<dependencies>
<group targetFramework=".NETFramework0.0" />
<group targetFramework="Windows0.0" />
<group targetFramework="WindowsPhone0.0" />
<group targetFramework="WindowsPhoneApp0.0" />
<group targetFramework=".NETStandard1.0">
<dependency id="NETStandard.Library" version="1.6.1" />
</group>
<group targetFramework="MonoAndroid1.0">
<dependency id="Xamarin.GooglePlayServices.Location" version="60.1142.0" />
<dependency id="Plugin.Permissions" version="2.2.1" />
</group>
<group targetFramework="Xamarin.iOS1.0">
<dependency id="Plugin.Permissions" version="2.2.1" />
</group>
<group targetFramework="Xamarin.Mac2.0" />
<group targetFramework=".NETPortable0.0-Profile259" />
<group targetFramework="UAP0.0" />
<group targetFramework=".NETPlatform5.0" />
<group targetFramework="Xamarin.TVOS0.0" />
<group targetFramework="Xamarin.WatchOS0.0" />
</dependencies>
If you try other NuGet packages, such as say AutoMapper, then you will dependencies when you expand the Dependencies - NuGet - AutoMapper item in the Solution Explorer.

Related

How to create Nuget package with nested dependencies

I'm working on a .NET Core solution. For one of the projects within the solution, I need to build a Nuget package.
Project A has a reference to another project B in the solution, set up as a project reference. Project B has a dependency on a Nuget package C.
Now, when I create a Nuget package for A, it includes A.dll and B.dll but not C.dll
Can someone help me figure this out? How can I include all 3 .dlls?
Thanks,
Andy
You can certainly solve this by creating your own nuspec file. I am not sure how to do it within the context of the csproj file.
For example, with #csla we manage all our own nuspec files because there are so many moving parts.
Within a nuspec file you can list the specific files you want included, along with any package dependencies. So in your example it sounds like your nuspec would include the project A and B assemblies, so something like this:
<files>
<file src="..\..\bin\Release\netstandard\netstandard2.1\**\A.dll" target="lib\netstandard2.1" />
<file src="..\..\bin\Release\netstandard\netstandard2.1\**\B.dll" target="lib\netstandard2.1" />
</files>
And would declare the dependency to package C.
<dependencies>
<group targetFramework="netstandard2.1">
<dependency id="C" version="1.0.0" />
</group>
</dependencies>
You can see numerous examples in the #csla repo. Perhaps the closest (not using wildcards) is the Csla.Blazor.nuspec file.
See https://github.com/NuGet/Home/issues/3891 for the feature request for dotnet.exe pack to the nuget client team. There are workarounds and debates in that issue.
Thx, Rob Relyea, NuGet Client Team

How can I make an assembly for .net core 3.1 and .netstandard2.0?

Can anyone please tell me what's the correct approach? This is my project file
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>
and this is parts of the nuspec file
<dependencies>
<group targetFramework=".NETStandard2.1">
<dependency id="Microsoft.CSharp" version="4.7.0" />
</group>
<group targetFramework=".NetCore,Version=3.1">
<dependency id="Microsoft.CSharp" version="4.7.0" />
</group>
</dependencies>
<packageTypes>
<packageType name="Dependency" />
</packageTypes>
</metadata>
<files>
<file src="bin\$configuration$\**\*.*" exclude="**\*.pdb" target=".\lib"/>
</files>
When building the assembly using Cake we specify Win-x64 as the runtime. Is this correct?
The file/folder structure in the generated nupkg is
\lib
\netcoreapp3.1
\any
\win
\win-x64
\netstandard2.0
\win10-x64
Tools: VS2019, NuGet v5.4.0
Then when I try to install it in a .net core 3.1 project I get the dreaded:
Error NU1202 Package JDM.Common.Json 0.2.2 is not compatible with netcoreapp3.1 (.NETCoreApp,Version=v3.1). Package JDM.Common.Json 0.2.2 does not support any target frameworks. ...
I must admit that not being able to get this working is driving me crazy.
TIA
There is no need to create a nuspec file for this. You can use the plural TargetFrameworks and specify multiple target frameworks:
<PropertyGroup>
<TargetFramework>netstandard2.1;netcoreapp3.1</TargetFramework>
</PropertyGroup>
Then you can create the .nupk file using dotnet pack

Dependencies in Nuspec vs. csproj

I have a Dotnet Core 2.1 project which has both a nuspec and a csproj file - one major hassle is that the csproj describes dependencies like this:
<ItemGroup>
<PackageReference Include="Refit" Version="4.6.16" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1" />
<PackageReference Include="Refit.HttpClientFactory" Version="4.6.16" />
</ItemGroup>
While the nuspec does this:
<dependencies>
<dependency id="Refit" version="4.6.16" />
<dependency id="Refit.HttpClientFactory" version="4.6.16" />
<dependency id="Microsoft.AspNetCore.All" version="2.1" />
</dependencies>
Both are easily out of sync and keeping the same information twice is annoying.
Is there a way to avoid that?
There is certain to be a easy way for this, just use dotnet pack instead of nuget pack and .csproj files instead of .nuspec files.
dotnet pack supports 2 ways to specify the nuget package properties.
The legacy way: using .nuspec file, which would disable the 2nd way
The new way: specifying them in .csproj file
dotnet pack supports both ways but you must add a NuspecFile property to reference the .nuspec file and there are a lot of bugs and feature missings for the legacy way, which means you can only use the new one.
dotnet pack executes restore and build on the project and packs it with a automatically generated .nuspec file resolving all nuget metadata properties in .csproj as .nuspec properties and all projects references as nuget package references (This is not available with manually specified .nuspec file), so that versioning, dependency, and package file structure things can be automatically ensured.
My own library could be an example. Version and dependency things are specified for only once at where they are supposed to be and there are no longer any annoying duplicate configurations. Executing dotnet pack on the solution directory would generate all good .nupkgs on the dist directory.

Change "Referencee" $(PackageVersion) During DNCore Pack

I am trying to use MSBuild to automatically update package versions based on the branch name. This works for the project itself, but referenced projects (that use the same MSBuild targets) use the default version - meaning that my targets are not running. For example, assume I have the following projects:
ConsoleApp1
ProjectReference: ClassLibrary1
ClassLibrary1
When building the above, I get the following nuspec/nugets:
ConsoleApp1 version 0.0.2-beta00001
dependency id="ClassLibrary1" version="1.0.0"
ClassLibrary version 0.0.2-beta00001
Note that the PackageVersion that is being pulled through is the default for the ProjectReference, while the project itself is building with the discovered package version.
I've tried changing GetTargetPathDependsOn as well as BeforeTargets="GetTargetPath;GetProjectsReferencingProjectJson" (after poking around in the Nuget Pack MSBuild), but they don't seem to be having an effect.
<PropertyGroup>
<BuildDependsOn>
OverridePackageVersion;
$(BuildDependsOn);
</BuildDependsOn>
<GetTargetPathDependsOn>
OverridePackageVersion;
$(GetTargetPathDependsOn);
</GetTargetPathDependsOn>
</PropertyGroup>
<Target Name="OverridePackageVersion"
BeforeTargets="GetTargetPath;GetProjectsReferencingProjectJson"
DependsOnTargets="GetDefaultVersion">
<CreateProperty
Value=""
Condition="'$(AutoPackagePreName)'=='$(ReleaseBranchName)'">
<Output TaskParameter="Value" PropertyName="AutoPackagePreName" />
</CreateProperty>
<CreateProperty
Value="$([System.String]::Format( $(AutoPackagePreNumberFormat), $([MSBuild]::Add($(AutoPackagePreNumber), 0)) ))">
<Output TaskParameter="Value" PropertyName="AutoPackagePreNumber" />
</CreateProperty>
<!-- Final Override -->
<CreateProperty
Value="$(AutoPackageVersion)"
Condition="'$(AutoPackagePreName)'==''">
<Output TaskParameter="Value" PropertyName="PackageVersion" />
</CreateProperty>
<CreateProperty
Value="$(AutoPackageVersion)-$(AutoPackagePreName)$(AutoPackagePreNumber)"
Condition="'$(AutoPackagePreName)'!=''">
<Output TaskParameter="Value" PropertyName="PackageVersion" />
</CreateProperty>
<CreateProperty
Value="$(PackageVersion)"
Condition="'$(UpdateVersion)'=='true'">
<Output TaskParameter="Value" PropertyName="Version" />
</CreateProperty>
<Message Importance="High" Text="Selected package version $(PackageVersion)." />
</Target>
Is this at all possible, or am I going to have to use Powershell in my CI?
The full source is available.
The targets you'd need to run before for the recent NuGet and .NET Core 2.* SDK versions are CollectPackageReferences;PrepareForBuild. To get it working in older versions, I used Restore;_GenerateRestoreProjectSpec in addition but these should no longer be necessary on recent tooling. See my Directory.Builds.targets i'm using to create a public NuGet package.
At the moment, dependency package versions are locked down during restore time and read from the obj\project.assets.json file, this is why the restore-specific targets are used. Note that restore doesn't import props/targets files from NuGet packages so you currently cannot consume versioning logic via a NuGet package containing build assets that work for project-to-project references. See the GitHub issue for it - the plan seems to be to move from reading the assets file to re-evaluating the versions from referenced projects instead of locking them down during restore.

How to include the multiple .NET Standard versions in the NuGet package

I have created the two projects with respect to support .NET Standard version 1.2 & 1.4 and refer the project.json as per target version. Then create the NuGet package with nuspec below.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>package id</id>
<version>15.1120.0.1</version>
<authors></authors>
<owners></owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl> </licenseUrl>
<projectUrl></projectUrl>
<iconUrl> </iconUrl>
<description> </description>
<copyright></copyright>
<tags> </tags>
<dependencies>
<group targetFramework=".NETStandard1.2">
<dependency id="Microsoft.NETCore.Portable.Compatibility"
version="1.0.1" />
<dependency id="NETStandard.Library" version="1.6.0" />
</group>
<group targetFramework=".NETStandard1.4">
<dependency id="Microsoft.NETCore.Portable.Compatibility" version="1.0.1" />
<dependency id="NETStandard.Library" version="1.6.0" />
</group>
</dependencies>
</metadata>
</package>
It creates the package properly. Now I want to refer this package in the .NET core 1.0 version application with .NET framework 4.6.1. As pre-the .NET Standard Support It should refer the .NET Standard 1.4 version. But it refers .NET Standard 1.2 reference. What I was missing in the package creation. Also,can we please let me know whether we can include multiple target in .NET Standard or not?

Resources