0

I have a solution with multiple projects and these projects have nuget packages installed which are different in version. Looks when solution is rebuild, the version of dll copied to output directory is not deterministic and often I end up with runtime "file not found" exception for obvious reason. I will try to over simply the problem with below example :

Let's say ProjectA is cossole application and refers version 1.0.0 of assembly xyz.

ProjectA also refers to ProjectB in same solution via project reference. Now let say ProjectB references version 2.0.0 of assembly xyz.

I would like to know when solution is rebuild, is it deterministic which version of xyz dll will be copied to output directory ? If no, is there a way to ensure this. I know in that case I need to update config with appropriate binding re direction policy.

rahulaga-msft
  • 3,964
  • 6
  • 26
  • 44
  • This is supposed to be resolved by MSBuild, it looks at the references and their dependencies and tries to find a solution. Adding BindingRedirects to the config file as needed to convince the CLR that it might work. Without a detailed build trace it is just guessing why this did not happen. Consider linking to a paste-bin to get this question answered. – Hans Passant Mar 15 '18 at 13:17
  • @HansPassant : here is [link](https://pastebin.com/im6hdFrC) to paste bin. so it is log for - projectA (console app) refers to ProjectB class library. ProjectB refers to version 8.0.0 of Newtonsoft.json.dll where as ProjectA has version 11.0.0 of Newtonsoft.json.dll. However, my final o/p directory after rebuild have version 11.0.0. Am trying to understand from log if msbuild initially copied version 8.0.0 and then overwrite it with version 11.0.0. – rahulaga-msft Mar 16 '18 at 11:05

1 Answers1

2

I would like to know when solution is rebuild, is it deterministic which version of xyz dll will be copied to output directory?

Yes, the version 1.0.0 of xyz dll will be copied to output directory.

According to the document Dependency resolution with PackageReference:

When the package graph for an application contains different versions of the same package, NuGet chooses the package that's closest to the application in the graph and ignores all others. This behavior allows an application to override any particular package version in the dependency graph.

In you case, the version 1.0.0 of xyz.dll is nearer to the projectA in the graph, that version will be copied to the output directory.

Then I also created a test package xyz with version 1.0.0 and 2.0.0, add those two nuget package to the projectA and projectB, then ProjectA also refers to ProjectB, after build, the version 1.0.0 xyz.dll copied to the output directory:

enter image description here

Update:

Can you check and confirm on the behavior when dll version is different in ProjectA and ProjectB \

To verify this question, I have created a project xyz, generated the version 1.0.0 xyz.dll and 2.0.0 xyz.dll, then refers 2.0.0 xyz.dll to the project B and 1.0.0 xyz.dll to the project A, build the solution, got the same result: 1.0.0 xyz.dll will be copied to the output directory:

enter image description here

As the above test results, 1.0.0 xyz.dll will be copied to the output directory. When you got the file not found error, please check if you are invoke the method in version 2.0.0 the xyz.dll.

Update2:

screen shot you showing says file version (but file version is not same as assembly version)

That because I want to be able check the AssemblyVersion in the windows explorer more convenient, I change the AssemblyVersion and AssemblyFileVersion at the same time before gnenerating the different version dll:

Like:

1.0.0 xyz.dll:

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

2.0.0xyz.dll:

[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

So we just need check the file version instead of assembly version in wondows explorer for more convenient.

Hope this helps.

Leo Liu
  • 71,098
  • 10
  • 114
  • 135
  • Thanks !! But i am not referring to nuget or file version, I am referring to assembly version. But as per your explanation, looks it still will choose deterministic version 1.0.0 of assembly. Can you check and confirm on the behavior when dll version is different in ProjectA and ProjectB \ – rahulaga-msft Mar 16 '18 at 06:02
  • @RahulAgarwal, Do you mean reference different version of dll file directly to Project A and Project B? – Leo Liu Mar 16 '18 at 06:09
  • yes, i think i kind of miscommunicated in OP by saying different nuget version. But i assumed people will take different nuget package version will have different assembly version as well. – rahulaga-msft Mar 16 '18 at 06:11
  • @RahulAgarwal, I have test it with different version of dll file directly to Project A and Project B, but got the same result. Check my updated answer for details. – Leo Liu Mar 16 '18 at 06:39
  • Thanks !! Is there any documentation which says how msbuild resolves assembly reference graph. Is "close to" concept applicable in that case also. Also just for FYI..screen shot you showing says file version (but file version is not same as assembly version) – rahulaga-msft Mar 16 '18 at 07:55
  • @RahulAgarwal, I have not found the official document about this for C# programming, but just as you said, nuget package should have the same behavior as C#. In the nuget official document, it declare that using the "close to" assembly. And some other answer also support this opinion: **If any kind of element from a dependency is used directly from the project where the assembly is referenced, that reference will be copied.** https://stackoverflow.com/questions/26163368/is-copy-local-transitive-for-project-references/26163944#26163944 – Leo Liu Mar 16 '18 at 08:27
  • @RahulAgarwal, for your second question "screen shot you showing says file version (but file version is not same as assembly version)", I explained the reason in my update2 answer, you can check it for more details. – Leo Liu Mar 16 '18 at 08:40
  • Thanks, i did not noticed update. Also msbuild refers to `ResolveAssemblyReference Task` [msdn link here](https://msdn.microsoft.com/en-us/library/9ad3f294.aspx) to resolve these references. – rahulaga-msft Mar 16 '18 at 13:38
  • @RahulAgarwal, Yes, I also found that document, but it only provide us the task, not much more explanation the "close to". But as we test the "close to" should be correct, what is your question now? – Leo Liu Mar 16 '18 at 18:55
  • I deeply appreciate you guys share these ideas, I also confused about such thing before, after read, I have another question: if say A -> B, and A ->C, B,C is at the same level to project A, if B, C both reference an assmebly D which has different version: B reference D on ver 1.0 and C reference D on ver 2.0, which version D assembly is copied under A's bin folder after build? – IcyBrk Jul 29 '19 at 20:27