Dependency loading error when using a .Net Standard Xamarin.Forms project in an iOS app

Hi,

This question is about the use of .Net Standard in a Xamarin.Forms project targeting iOS (but also Android).

<rant>
Please excuse my frustration but with the transition between PCL to .Net Standard I feel we are in a kind of limbo with very little working out of the box and very little information on how to deal with edge cases or not-even-so-edgy-cases.

I've read (many)(different) guides and the vocabulary is mildly confusing as well as the fact that you need to edit your .csproj files will small undocumented hacks to work around things that aren't working out of the box yet (many NuGet related issues that aren't approached in the Hi! This is how you convert from PCL to the great .Net Standard happy videos).
</rant>

I've read through
https://forums.xamarin.com/discussion/86139/targeting-net-standard/p1
https://blog.xamarin.com/building-xamarin-forms-apps-net-standard/
https://channel9.msdn.com/Shows/XamarinShow/Snack-Pack-15-Upgrading-to-XamarinForms-to-NET-Standard
https://developer.xamarin.com/guides/cross-platform/application_fundamentals/net-standard/
https://stackoverflow.com/questions/tagged/.net-standard+xamarin.forms
http://lastexitcode.com/blog/2017/06/04/NuGetSupportInVisualStudioMac7-0/

What I've done
1. Created a new blank Xamarin.Forms app, targeting iOS and Android and using PCL, using Visual Studio for Mac
2. Following the steps of @JamesMontemagno, created a new .Net Standard library project and added Xamarin.Forms 2.4.0 via Nuget
If I understand well, at this point, my new core application project is a .Net Core project.
3. Added NuGet dependency toward Microsoft.Rest.ClientRuntime because my application uses an autogenerated REST Api definition created using autorest
4. Added my core application project as a reference to my iOS project. Question here: What type or project is the iOS project here? .Net Framework project? Or something else? How do/can I create a .Net Core/Standard iOS project?

Then I build and run my application. When I hit a button that trigger the use of Microsoft.Rest.ClientRuntime, I get the following error:

Could not load type of field 'MyApp.MyPage+d__3:5__2' (4) due to: Could not load file or assembly 'Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. assembly:Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 type: member:

If I add Microsoft.Rest.ClientRuntime NuGet package as a dependency to the iOS project then it does work but:
1. It's pulling a hell lot of NuGet dependencies
2. That's not how it used to work with PCL

So I wondered if there's anything documented about referencing .Net Standard from old-not-so-standard projects (<rant>A problem not approached in the happy-little-videos</rant>) and found this:
https://www.hanselman.com/blog/ReferencingNETStandardAssembliesFromBothNETCoreAndNETFramework.aspx

But it does not seem to work, at least not for my iOS project using Visual Studio for Mac.

Any suggestion on how to solve this? Or how am I supposed to set up my iOS app project to use the .Net Standard project?

Best Answers

  • ThibaultDThibaultD SE ✭✭✭
    Accepted Answer

    To sum up the solution is to:

    @mattward said:
    If you want to avoid a lot of NuGet dependencies you could switch to using PackageReferences in the iOS project instead of using a packages.config file. If you are using VS for Mac then currently you will need to add one PackageReference into the .csproj manually by using a text editor. Once the project has a single PackageReference then VS Mac will use PackageReferences in the project file from then on.

    <ItemGroup>
        <PackageReference Include="Xamarin.Forms" Version="2.4.0.280" />
    </ItemGroup>
    

    and perform a fair amount of NuGet restore/clean/rebuild.

    Also make sure to use a rather new Mono version (Mono 5.4.1.6 works, Mono 4.8.0 does not).

Answers

  • ThibaultDThibaultD SEMember ✭✭✭
    edited November 2017

    Hi @mattward and thank you for your prompt answer.

    @mattward said:
    In what follows I am assuming that your .NETStandard project also uses PackageReferences since you mention that you created a .NET Core project.

    Yes, sorry I did not include the project contents the first time, it looks like:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>netstandard1.4</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <Folder Include="MyAppBackend\" /><!-- code generated by autorest -->
      </ItemGroup>
      <ItemGroup>
        <None Remove="App.xaml" />
      </ItemGroup>
      <ItemGroup>
        <Compile Update="App.xaml.cs">
          <DependentUpon>App.xaml</DependentUpon>
          <SubType>Code</SubType>
        </Compile>
      </ItemGroup>
      <ItemGroup>
        <PackageReference Include="Xamarin.Forms" Version="2.4.0.91020" />
        <PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.10" />
      </ItemGroup>
    </Project>
    

    @mattward said:
    If you want to avoid a lot of NuGet dependencies you could switch to using PackageReferences in the iOS project instead of using a packages.config file. If you are using VS for Mac then currently you will need to add one PackageReference into the .csproj manually by using a text editor. Once the project has a single PackageReference then VS Mac will use PackageReferences in the project file from then on.

    <ItemGroup>
        <PackageReference Include="Xamarin.Forms" Version="2.4.0.280" />
    </ItemGroup>
    

    Using the RestoreProjectStyle MSBuild property does not currently work in VS for Mac but will in a later release.

    The Xamarin.Forms reference is not a problem since I still have the old references in the iOS csproj:

      <ItemGroup>
        <Reference Include="System" />
        <Reference Include="System.Xml" />
        <Reference Include="System.Core" />
        <Reference Include="Xamarin.iOS" />
        <Reference Include="Xamarin.Forms.Core">
          <HintPath>..\packages\Xamarin.Forms.2.4.0.91020\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath>
        </Reference>
        <Reference Include="Xamarin.Forms.Platform">
          <HintPath>..\packages\Xamarin.Forms.2.4.0.91020\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll</HintPath>
        </Reference>
        <Reference Include="Xamarin.Forms.Platform.iOS">
          <HintPath>..\packages\Xamarin.Forms.2.4.0.91020\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll</HintPath>
        </Reference>
        <Reference Include="Xamarin.Forms.Xaml">
          <HintPath>..\packages\Xamarin.Forms.2.4.0.91020\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll</HintPath>
        </Reference>
      </ItemGroup>
    

    The one I want to add is Microsoft.Rest.ClientRuntime (and its dependencies).
    Following you advice, I've added this to the (not .Net Core) iOS project:

       <ItemGroup>
         <PackageReference Include="Xamarin.Forms" Version="2.4.0.91020" />
         <PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.10" />
       </ItemGroup>
    

    But I still get the same error.
    The only change is that Microsoft.Rest.ClientRuntime now appears as package under the iOS project:

    But neither Microsoft.Rest.ClientRuntime.dll nor any of its dependencies are added to directory
    bin/iPhoneSimulator/Debug/device-builds/iphone9.1-11.1/MyAppiOS.app/

    Have I missed something? Do I need to create a ".Net Core"-iOS project, if so how?

    @mattward said:
    Using the RestoreProjectStyle MSBuild property does not currently work in VS for Mac but will in a later release.

    Ok thank you, good to know.

  • mattwardmattward GBMember Xamurai

    Ah, OK. So the problem is that the assemblies are not in the .app. They seem to be in the bin folder. Using a packages.config file or a PackageReference should not affect this.

    I can reproduce the Microsoft.Rest.ClientRuntime.dll not being added to the .app if the .NET Standard project has no code that uses any types from the Microsoft.Rest.ClientRuntime.dll. The iOS project I have is using a class from the .NET Standard project so the .NET Standard project assembly is added to the .app. When the .NET Standard project has a class that uses say Microsoft.Rest.BasicAuthenticationCredentials then, on rebuilding, the .app contains the Microsoft.Rest.ClientRuntime.dll. In my case presumably the iOS linker is seeing that the assembly is not used and is not including it.

  • ThibaultDThibaultD SEMember ✭✭✭
    edited November 2017

    Hi Matt,

    I really appreciate that you take the time to help here.

    @mattward said:
    I can reproduce the Microsoft.Rest.ClientRuntime.dll not being added to the .app if the .NET Standard project has no code that uses any types from the Microsoft.Rest.ClientRuntime.dll. The iOS project I have is using a class from the .NET Standard project so the .NET Standard project assembly is added to the .app. When the .NET Standard project has a class that uses say Microsoft.Rest.BasicAuthenticationCredentials then, on rebuilding, the .app contains the Microsoft.Rest.ClientRuntime.dll. In my case presumably the iOS linker is seeing that the assembly is not used and is not including it.

    My iOS application references the .Net Standard.
    The .Net Standard project does use Microsoft.Rest.ClientRuntime.dll, which is the reason why it crashes (since the dll is missing). Microsoft.Rest.ClientRuntime.dll library is used by the code that is autogenerated by autorest, if that makes any change.

    I have tried to create a new BasicAuthenticationCredentials but did stumble on the same error.

    I have created a minimalistic repro-project and uploaded here:
    https://github.com/durandt/NetStandardiOSLinkError

    First commit (561a5c2d1223b4701d39a4701b0198f72d60786f) just creates a new Microsoft.Rest.BasicAuthenticationCredentials in a PCL project that is referenced by the iOS app.

    Second commit (0bf6af1dd344c995d51aa11c301130848352b874) upgrades from PCL to .Net Standard using @JamesMontemagno's guide .

    Third commit (c30f133313c8f1c29e206e8d403eca9d313483c5) adds the PackageReference as suggested above.

    Can you see any difference in settings with your own repro-project?

  • mattwardmattward GBMember Xamurai

    I tried your solution and built it locally and an .app was created in the NetStandardiOSLinkError/iOS/bin/iPhoneSimulator/Debug/device-builds/iphone10.3-11.0 directory and it contains the Microsoft.Rest.ClientRuntime.dll. The app also runs in the simulator without crashing.

    There are a few problems in the iOS project but it looks like they have no affect on my machine (the iOS project does not need to explicitly reference the Xamarin.Forms dlls nor import the Xamarin.Forms .targets and .props if you are using PackageReferences).

    I am however most likely using different versions of Xamarin.iOS, VS for Mac and Mono. Can you post the information from VS for Mac's About dialog - show details?

  • ThibaultDThibaultD SEMember ✭✭✭

    @mattward said:
    I am however most likely using different versions of Xamarin.iOS, VS for Mac and Mono. Can you post the information from VS for Mac's About dialog - show details?

    Ah.

    Visual Studio Community 2017 for Mac
    Version 7.2.2 (build 11)
    Installation UUID: b71d3799-638b-4e58-854f-b89d8107d7af
    Runtime:
    Mono 5.4.1.6 (2017-06/1f4613aa1ac) (64-bit)

    NuGet
    Version: 4.3.1.4445

    .NET Core
    Runtime: Not installed
    SDK: Not installed
    MSBuild SDKs: /Library/Frameworks/Mono.framework/Versions/4.8.0/lib/mono/msbuild/15.0/bin/Sdks

    Apple Developer Tools
    Xcode 9.1 (13532)
    Build 9B55

    Xamarin.iOS
    Version: 11.3.0.47 (Visual Studio Community)
    Hash: 51128b8c
    Branch: xcode9.1
    Build date: 2017-10-31 22:42:13-0400

    Copying the details I did then realize that I was using Mono 4.8.0 instead of Mono 5.4.1.6 to build... (Changing back and forth for old legacy projects).
    It seems to work just as you describe when using Mono 5.4.1.6.

    Thank you for your help, sorry to have disturbed you for such an error.

  • ThibaultDThibaultD SEMember ✭✭✭
    Accepted Answer

    To sum up the solution is to:

    @mattward said:
    If you want to avoid a lot of NuGet dependencies you could switch to using PackageReferences in the iOS project instead of using a packages.config file. If you are using VS for Mac then currently you will need to add one PackageReference into the .csproj manually by using a text editor. Once the project has a single PackageReference then VS Mac will use PackageReferences in the project file from then on.

    <ItemGroup>
        <PackageReference Include="Xamarin.Forms" Version="2.4.0.280" />
    </ItemGroup>
    

    and perform a fair amount of NuGet restore/clean/rebuild.

    Also make sure to use a rather new Mono version (Mono 5.4.1.6 works, Mono 4.8.0 does not).

  • Ajay87Ajay87 INMember ✭✭
    edited February 2018

    @ThibaultD @mattward
    When i build the ios project in visual studio 2015 on windows after connected with the mac os, I am getting this error
    "Error Could not link assemblies. Reason: Object reference not set to an instance of an object"
    How can i fix this..

  • Hi @ThibaultD @mattward , Please let me know how you fixed it since I am getting the same error.

  • mhdmaktabimhdmaktabi Member ✭✭

    I'm unable to compile my Xamarin.iOS project. This project was recently migrated from .NET Standard 1.4 to a .NET Standard 2 project in VS2017 on Windows connect to the Mac Agent.

    I'm getting this error:

    Error: Could not link assemblies. Reason: Error while processing references of 'Clients.iOS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'

    This is part of the Build log:

    warning MSB3276: Found conflicts between different versions of the same dependent assembly. Please set the "AutoGenerateBindingRedirects" property to true in the project file.

    Consider app.config remapping of assembly "System.Runtime, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" from Version "4.0.0.0" to Version "4.0.20.0" [] to solve conflict and get rid of warning.rning.

    (1,1): error: Xamarin.FFImageLoading package not found for versions [2.2.20, ] on netstandard1.4

Sign In or Register to comment.