Bug 43713 - When a .NET Standard library is added to a Xamarin.iOS project it does not seem to properly bring in the dependent assemblies.
Summary: When a .NET Standard library is added to a Xamarin.iOS project it does not se...
Status: RESOLVED NOT_ON_ROADMAP
Alias: None
Product: Tools
Classification: Mono
Component: xbuild ()
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: Future Cycle (TBD)
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2016-08-24 18:34 UTC by Mike Smith
Modified: 2018-03-15 10:39 UTC (History)
7 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Project demonstrating "Could not load file or assembly" exception (47.65 KB, application/zip)
2016-08-24 18:34 UTC, Mike Smith
Details
Non-Xamarin test case that hits the same problem (18.27 KB, application/zip)
2016-08-24 20:58 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details
Non-Xamarin test case diagnostic MSBuild output (927.84 KB, text/plain)
2016-08-24 20:59 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED NOT_ON_ROADMAP

Description Mike Smith 2016-08-24 18:34:45 UTC
Created attachment 17197 [details]
Project demonstrating "Could not load file or assembly" exception

=== Overview ===

When a .NET Standard library is added to a Xamarin.iOS project it does not seem to properly bring in the dependent assemblies.

=== Background ===
	
In the attached project (StdiOS4), there is a iOS single view iPhone app (just the starter template with a label added to the view controller) and a .NET Standard library.  The standard library contains a class with a single method:

        public static void Test()
        {
            JsonConvert.DeserializeObject("{\"a\":null}");
        } 

The Newtonsoft.Json  Nuget package is added to the .NET Standard library.

 In the ViewDidLoad method of the view controller a call is made to a method in a .NET Standard Library Test() method.

This fails with a "Could not load file or assembly" exception.

=== Steps to Reproduce  ===

Create iOS iPhone single view app
Add .NET Standard library project
Add method that depends on a Nuget (Newtonsoft.Json, for example) to the .NET Standard library
Add Nuget package to the .NET Standard library
Call .NET Standard library method in iOS app

=== Expected Behavior ===

When the app is run, expect that the .NET Standard library method can be called successfully from the iOS app.

=== Actual Behavior ===

Got exception when attempting to call the method in the .NET Standard library:

System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.

=== Build Information ===

Microsoft Visual Studio Enterprise 2015
Version 14.0.25421.03 Update 3
Microsoft .NET Framework
Version 4.6.01038

Installed Version: Enterprise

Visual C# 2015   00322-80000-00000-AA822
Microsoft Visual C# 2015

Xamarin   4.1.2.18 (fcbe082)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.

Xamarin.Android   6.1.2.21 (1cf254d)
Visual Studio extension to enable development for Xamarin.Android.

Xamarin.iOS   9.8.2.22 (f37444a)
Visual Studio extension to enable development for Xamarin.iOS.

=== Notes ===

Have identified the following work-around:

-- Instead of adding a .NET Standard library, add a PCL library.
-- Get the project to run successfully
-- Remove the Nuget packages from the PCL library
-- Convert the PCL into a .NET Standard library 
-- Add the Nuget packages back in to the .NET Standard library
-- Run the project again.  
-- The project should run successfully

I noticed that with the .NET Standard library, the Newtonsoft.Json dll does not wind up in the /bin folder of the app.  If the PCL is added first and then converted into a .NET Standard library then that dll does wind up in the /bin folder.  I tried just adding the dll to the bin folder (without involving a PCL, just using the .NET Standard library) but that didn't seem to work.
Comment 1 Brendan Zagaeski (Xamarin Team, assistant) 2016-08-24 20:23:23 UTC
## Simpler workaround

Install the Newtonsoft.Json package in the iOS app project as well.


This sort of "imitates" the approach that one would take for NuGet packages that use the "bait and switch" design [1] to provide platform-specific functionality.  But the Newtonsoft.Json package does not contain any platform-specific code, so I believe it should be behave just like any pure portable class library: it should not be necessary to reference it directly in the app project.

[1] http://log.paulbetts.org/the-bait-and-switch-pcl-trick/




## Note to the Xamarin team

I will mark the bug as Confirmed in a moment, after I collect the diagnostic build output and test a few version statuses.
Comment 2 Mike Smith 2016-08-24 20:35:14 UTC
Unfortunately the work-around of adding the PCL and then switching to a .NET Standard library will not work.  As soon as the project is cleaned it removes the assembly left-over from the PCL.
Comment 3 Brendan Zagaeski (Xamarin Team, assistant) 2016-08-24 20:58:46 UTC
Created attachment 17199 [details]
Non-Xamarin test case that hits the same problem

## Status update: Appears to be Upstream

If this is indeed an incorrect behavior, then it appears to be an upstream bug, perhaps in the general C# targets that are shipped as part of Visual Studio and the Microsoft Build Tools themselves.




## Steps I followed to replicate without Xamarin


1. Open Visual Studio 2015 Update 3 on a Windows 10 image that has never had Xamarin installed.


2. Create a new "Visual C# > Console Application" (.NET Framework 4.5.2).


3. Add a new "Visual C# > Class Library (Portable)" project to the solution.


4. Convert the portable class library to "Target .NET Platform Standard" under "Project Properties > Library > Targeting" (I used ".NETStandard1.2").


5. Add the Newtonsoft.Json NuGet package to the portable class library.


6. Add a call to Newtonsoft.Json in the portable class library, for example:
var x = new Newtonsoft.Json.JsonSerializer();


7. Add a reference to the portable class library in the Console Application and then add a call to the constructor from step 6.


8. Attempt to run the console application.




## Results

The application hits the same missing assembly exception at run time as the iOS project does:

> System.IO.FileNotFoundException was unhandled
>   FileName=Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
>   FusionLog==== Pre-bind state information ===
> LOG: DisplayName = Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
>  (Fully-specified)
> LOG: Appbase = file:///c:/source/ConsoleApplication1/ConsoleApplication1/bin/Debug/
> LOG: Initial PrivatePath = NULL
> Calling assembly : PortableClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
> ===
> LOG: This bind starts in default load context.
> LOG: Using application configuration file: c:\source\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.vshost.exe.Config
> LOG: Using host configuration file: 
> LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
> LOG: Post-policy reference: Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
> LOG: The same bind was seen before, and was failed with hr = 0x80070002.
> 
>   HResult=-2147024894
>   Message=Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
>   Source=PortableClassLibrary1
>   StackTrace:
>        at PortableClassLibrary1.Class1..ctor()
>        at ConsoleApplication1.Program.Main(String[] args) in c:\source\ConsoleApplication1\ConsoleApplication1\Program.cs:line 13
>        at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
>        at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
>        at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
>        at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
>        at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
>        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
>        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
>        at System.Threading.ThreadHelper.ThreadStart()
>   InnerException:
Comment 4 Brendan Zagaeski (Xamarin Team, assistant) 2016-08-24 20:59:28 UTC
Created attachment 17200 [details]
Non-Xamarin test case diagnostic MSBuild output
Comment 5 Alexander Köplinger [MSFT] 2016-08-31 15:32:54 UTC
This is a known limitation right now that is not specific to Xamarin.

When referencing a project.json-based csproj (e.g. a netstandard class lib) from a packages.config-based csproj (e.g. a console app) the dependencies of the lib won't be added automatically because the NuGet msbuild task doesn't run, so it can't collect the dependencies from the project.json-based csproj and the console app basically sees a project with 0 references.

The workarounds are either to add the transitive dependencies manually, or switch the app project to be project.json-based as well.

I've been told that this is being redesigned as part of the project.json->MSBuild migration.
Comment 6 Marek Safar 2018-03-15 10:39:55 UTC
We deprecated xbuild and recommend using msbuild instead. Switching to msbuild will also most likely resolve the issue you reported.