Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Unit Test project(.NET 4.7) cannot load System.ValueTuple #476

Closed
gongdo opened this issue Aug 30, 2017 · 21 comments
Closed

Unit Test project(.NET 4.7) cannot load System.ValueTuple #476

gongdo opened this issue Aug 30, 2017 · 21 comments

Comments

@gongdo
Copy link

gongdo commented Aug 30, 2017

(The original issue was reported by Gyuwon Yi from here: https://developercommunity.visualstudio.com/content/problem/102236/unit-test-projectnet-47-cannot-load-systemvaluetup.html )

Unit Test project(.NET 4.7) referencing .NET Core library using value tuple cannot load System.ValueTuple assembly.
But console client application works correctly.
You can repro with code from https://github.com/gyuwon/ValueTypeTestingProblem

The whole message:

Test Name: Bar_returns_value_tuple_correctly
Test FullName: ValueTupleTestsNet47.FooService_specs.Bar_returns_value_tuple_correctly
Test Source: c:\users\gyuwon\Documents\Projects\ValueTupleTesting\ValueTupleTestsNet47\FooService_specs.cs : line 16
Test Outcome: Failed
Test Duration: 0:00:00.0261781 Result StackTrace: at ValueTupleTestsNet47.FooService_specs.Bar_returns_value_tuple_correctly()
Result Message:
Test method ValueTupleTestsNet47.FooService_specs.Bar_returns_value_tuple_correctly threw exception:
System.IO.FileLoadException: Could not load file or assembly 'System.ValueTuple, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

As I replied on the original issue, it can be solved by making library project to target multiple frameworks.
But it's just a work-around, not a solution.
I think it's not a single ValueTuple problem. There's some referencing issue on .NET Standard 2.0.
For example this issue on Azure Function(Web Job) project with .NET Standard 2.0 library, looks like similar: Azure/azure-functions-host#1792

@dasMulli
Copy link

dasMulli commented Aug 30, 2017

Does adding these properties to the test project's csproj file help?:

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

@gyuwon
Copy link

gyuwon commented Aug 31, 2017

@dasMulli Unfortunately BindingRedirect does not help. :'(

gyuwon added a commit to Reacture/Khala.Messaging that referenced this issue Aug 31, 2017
.NET Standard 2.0 호환성 문제로 인해 마이그레이션을 연기합니다.
참고: dotnet/standard#476

This reverts commit d7bd6c9.
gyuwon added a commit to Reacture/Khala.Messaging that referenced this issue Aug 31, 2017
.NET Standard 2.0 호환성 문제로 인해 마이그레이션을 연기합니다.
참고: dotnet/standard#476

This reverts commit e36dcbc.
gyuwon added a commit to Reacture/Khala.Messaging that referenced this issue Aug 31, 2017
.NET Standard 2.0 호환성 문제로 인해 마이그레이션을 연기합니다.
참고: dotnet/standard#476

This reverts commit 0cd42cf.
@FuncLun
Copy link

FuncLun commented Sep 2, 2017

This issue is easily reproduced by creating a .Net Standard 2.0 project with a function that uses a ValueTuple (such as public (int, int) Test() { return (1, 1); }) and calling that function (or calling any number of functions that eventually calls a ValueTuple function) from a .Net Framework application (such as unit test, console application, windows form, asp.net).

The exception occurs when the ValueTuple type is needed - not when a ValueTuple is passed from the .Net Standard to .Net Framework project. Actually, the ValueTuple does not even need to be used in the .Net Framework project.

When running under a .Net Core 2, the type is
System.ValueTuple, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.
When running under .Net Framework 4.6.1, the type is
System.ValueTuple, System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51.
But, when starting with a .Net Framework 4.6.1 applicaiton, the .Net Standard 2.0 code wants:
System.ValueTuple, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51

A workaround is to use a binding redirect in app.config:

      <dependentAssembly>
        <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
      </dependentAssembly>

However, this does not work in all situations. For example, some Unit Tests setups will execute from a separate folder and will not load the unit test projects app.config. Also, ComVisible projects will not use the app.config.

It seems that a simple version number change would resolve the issue.

I've seen quite a few issues on github due to the problem. This shows that many people are having trouble and spending time on this...
#446
dotnet/efcore#9046
julielerman/EFCore2NightlyNet461#1
ErikEJ/EntityFramework.SqlServerCompact#463
dotnet/roslyn#21832
and more...

@weshaggard
Copy link
Member

It seems that a simple version number change would resolve the issue.

Unfortunately that isn't possible because there are different assembly versions on different platforms and they already exist.

I agree this issue can be painful but the general issue stems from the .NET Framework being much more strict with assembly binding which is why you need the binding redirects.

If you guys can give me the scenarios where the binding redirects aren't working I can try and help figure out a solution.

@FuncLun
Copy link

FuncLun commented Sep 5, 2017

@weshaggard

If you guys can give me the scenarios where the binding redirects aren't working I can try and help figure out a solution.

These 2 situations are fairly easy to reproduce:

ComVisible: In a .Net Framework project, expose a class as [ComVisible(true)] that executes another function in a .Net Standard project that uses ValueTuple. Register the dll with regasm. In VBScript (or Classic ASP), use CreateObject on the .Net Framework object and call the function. App.Config files are not used for COM objects. Using AutoGenerateBindingRedirects creates the redirects in the output config file - which COM will not use.

PowerShell: Using the same .Net Framework object (ComVisible not necessary), Import the dll into powershell, use New-Object and call the function. Powershell does not use the app.config file.

@weshaggard
Copy link
Member

@ChrisW13 thanks for the scenarios.

@ericstj @terrajobst do you guys know whether the COM activation honors binding redirects?

For the Powershell or any case where there is an extension model (msbuild is another example) you are at the mercy of the host application to correctly load dependencies. In those cases you essentially are targeting a custom platform that the host application defines and you can only use things they allow. This isn't new but it is true that using .NET Standard 2.0 might make some of these issues more common. So there isn't any one generic solution to these problems depending on the host you might have to solve them differently,.

@rlordcardano
Copy link

Perhaps helpful: steps above didn't work for me with VS 2017 15.3.3, but started working with VS 2017 15.3.4.

@binarypatrick
Copy link

Can't seem to get this to work when running an azure function against a .net standard library

@terrajobst
Copy link
Member

terrajobst commented Oct 21, 2017

@binarypatrick

That's probably because Azure Functions don't work with .NET Standard 2.0 yet.

@binarypatrick
Copy link

Not even precompiled?

@binarypatrick
Copy link

This got things working for me. Seeing as there isn't a app.config this fix seems to work.

https://codopia.wordpress.com/2017/07/21/how-to-fix-the-assembly-binding-redirect-problem-in-azure-functions/

@KelsonBall
Copy link

I don't have an app.config file in my MS unit test projects, how do I apply the workaround?

@ericstj
Copy link
Member

ericstj commented Oct 24, 2017

Unit tests (both mstest and xunit) use the .dll.config convention.

@jnm2
Copy link

jnm2 commented Oct 24, 2017

NUnit picks up .dll.config as well.

@razvandbirle
Copy link

VS2017 15.4.0 here. not a Core2.0 project & the System.ValueTuple won't update / won't redirect.

@NiteLordz
Copy link

I am now having this issue as well. I created an Azure Function (HttpTrigger). It runs locally and even runs while deployed to Azure. However, it fails during CI check-in using VSTS with the same error message as above. I have tried the code workaround, I have tried added System.ValueTuple thru NuGet, all have failed. Is there a solution to have this build in VSTS?

@leftside
Copy link

leftside commented Feb 22, 2018

VS 15.5.7, .NET Standard 2.0, Azure Function project. Microsoft.NET.Sdk.Functions
(1.0.8). Won't build. Compile error in Visual Studio.

Error System.IO.FileNotFoundException: Could not load file or assembly 'System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.

@leftside
Copy link

Deleting the following folder worked for me. Project now compiles.
C:\Users\name.nuget\packages\microsoft.net.sdk.functions\1.0.8\build\netstandard1.0

Visual Studio 15.5.7, .NET Standard 2.0, Microsoft.NET.Sdk.Functions (1.0.8)

@gongdo
Copy link
Author

gongdo commented Jun 15, 2018

I'm closing this because it doesn't bother me anymore.

@GSPP
Copy link

GSPP commented Oct 15, 2018

@rrgurski
Copy link

rrgurski commented Mar 30, 2021

I ran into this problem today and solved by applying multiple framework targets for the .net-standard project.

That way the compiler compiles a version for each framework and links the correct one.

<PropertyGroup>
    <TargetFrameworks>net472;net5.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>

Note that it's TargetFrameworkS, plural.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests