Closed mocolicious closed 3 years ago
I am also having this problem, and reverting to 12.3.2 isn't an option for me.
How are you creating the release code?
msbuild from a root directory - Microsoft.Bcl.AsyncInterfaces is a package we reference elsewhere with 5.0.0.
using msbuild and then package deploy to .zip. Target framework netcoreapp2.2. tried it with multiple different target frameworks and had consistent problems.
Is Microsoft.Bcl.AsyncInterfaces
included in the zip you're deploying?
I've tried manually adding it and it doesn't work.
I was able to work around the issue by adding version redirects to everything in the world, including every .config file in the product.
Wouldn't you just need a redirect for Microsoft.Bcl.AsyncInterfaces
?
That's what I did, but I needed to do it in different places for different deployments, some of which made no sense. Things were working locally but not elsewhere.
There is another version of Microsoft.Bcl.AsyncInterfaces
somewhere? Possibly in the GAC?
@JoshClose I think that's what it is, its referencing it somewhere globally by default so it works in the debugger but on deployment does not
With 27.0.2 (in a .net 4.7.2 webapp) we face this bug too. On our dev machines it is working. On the Build-Server we have failing tests with the runtime exception mentioned above. Adding a assembly redirect fixes it:
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
The strange thing is, that the exception says v1.0.0.0 is missing. Why it wants 1.0.0.0 instead of the higher version actually referenced?
To be clear, We are using 27.0.2 in a .net standard 2.0 lib and this lib is tested in a xunit project that targets framework 4.7.2. The only way we were able to make this work was by pinning the transitive dependency of microsoft.bcl.asyncinterfaces to 1.1 in the .net standard library project.
FYI: I found an issue submitted to dotnet regarding this, and they said that binding redirects are the correct way to solve this, and it's a feature. This is intended behavior. There isn't anything on the CsvHelper side that can be changed to "fix" it, from what I understand.
Interesting, I know that we currently configure our projects to auto-generate binding redirects, so that is no longer sufficient and we must somehow know what packages we are using have as transitive dependencies and manually add binding redirects in our projects? Something about that just does not seem right to me. Normally, if you have a direct dependency and this dependency requires a specific version to work, the onus should normally be on you to pin the dependency to the correct version, not downstream consumers of that package... but I may be mistaken.
As a library, CsvHelper should be able to use whatever version it needs. Consumers of CsvHelper shouldn't have to worry about what version of any library is being used, and binding redirects should happen automatically in Visual Studio.
I know that we currently configure our projects to auto-generate binding redirects, so that is no longer sufficient and we must somehow know what packages we are using have as transitive dependencies and manually add binding redirects in our projects?
I have no clue. From my reading on how things are supposed to work, I as a library shouldn't worry about it. If things aren't working correctly, it's something that needs to be filed with .NET or NuGet.
Please link any relevant issues you find/create.
Here is another issue talking about this. #1488
And another. #1462
Strange because if I pin the transitive dependency to 1.1 for microsoft.bcl.asyncinterfaces, it all works. If you configured csvhelper to be pinned to that version it probably will "just work" for downstream consumers afterwards, wouldn't it? If I understand what is happening here, it's that v5.0.0 of Microsoft.Bcl.AsyncInterfaces is not compatible with csvhelper 27.0.2 because when I check our output folder, bcl.Async is there but cannot be loaded by csvhelper. by pinning that dependency to 1.1, then it all works, so either csvhelper needs to adapt the code to work with bcl.asyncInterfaces 5.0.0 OR it needs to pin that dependency to v1.1 which is the version that seems to be compatible from our testing here.
If I update to 5.0.0, will that cause problems for people using 1.1?
What is pinning? Do you have a link to the docs that discuss that?
This is what the references look like now.
<!-- .NET 4.5 -->
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup>
<!-- .NET 4.7 -->
<ItemGroup Condition="'$(TargetFramework)' == 'net47'">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.1.0" />
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
</ItemGroup>
<!-- .NET Standard 2.0 -->
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.1.0" />
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
</ItemGroup>
<!-- .NET Standard 2.1 -->
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
</ItemGroup>
When I say pin it's probably because that is how we refer to it when using paket. Paket allows to specify version or version subrange using semantic versionning to pull dependencies, for example a dependency of nuget somePackage ~> 5.5 will fetch the most recent available version of that package within 5.5 so if there is a 5.5.0 and 5.5.2 it will pull 5.5.2. if there is a 6.0 it will only fetch 5.5.2. There clearly is some breaking change between v5 and v1.1 of asyncinterfaces which is stopping it from being functional with csvhelper (so they probably have a breaking change here and that forces you to also have a breaking change or have some adaptation code that allows to step-up whatever is not compatible. Currently, you have to understand that your package shows as supporting any bcl.asyncinterfaces >= 1.1.0, since there is a v5 now available, any consumers of your package will automatically be pulling v5 and encounter the issue we are having unless they pin that package (force a specific version of that package) to 1.1. So your options are making it so your package does not support >= 1.1.0 but specifically 1.1.0 OR adapt the library to work with v5 and depending on what the breaking change is, you may need to have some adaptation code to make whatever that library consumes compatible from the old data. Your config looks good though, I'm starting to suspect that this may be a problem with paket, the other people having similar issues here are probably also on something like paket I imagine.. well, that is, if nuget reference for dependency locking is to be believed.
wait. I just noticed you specified 1.1.0, if you specify [1.1.0] then it should change the dependency to be = to 1.1.0 on your package instead of >= 1.1.0. as per package versioning
so the issue is 2-fold. 1: paket is not respecting the correct behaviour, since what you specified should normally take 1.1.0 or the closest minimal version available if that version is not available. This is a paket issue. But you are not actually compatible with v5 which is the latest available version for the async package, so you could more explicitly control the allowed versions by using the ( or [ etc markup for version referencing as specified in the package versioning doc which would be good since you don't want people getting v5 because it is clearly not compatible.
Microsoft.Bcl.AsyncInterfaces
5.0.0 uses a higher version of System.Threading.Tasks.Extensions
than what is referenced. Maybe that's where the issue lies.
I didn't know about the package version ranges. That's good to know.
I updated all the package references to the latest and there is no issue. I could release that and have all future release use the latest referenced packages.
maybe that is the issue, but it really is trying to resolve v 1.0.0 of bcl.async when version 5 is available which is really weird. but yes, updating all the refs (and possibly specifying with the square brackets or with a subrange such as 5.0. or 5.) would ensure that this does not happen until you actually want people to be getting a more recent version of those dependencies due to new features etc.
I'm starting to think that having packages configured with >= someVer is really not good since you are effectively at the mercy of whatever logic the package manager is using, in the case of nuget it means that version or next closest match, paket apparently sees that as latest available since you stated >= someVer.
For example: "Many package authors made the mistake of omitting the brackets, effectively specifying >= 1.2.3 when they wanted to specify = 1.2.3" taken from paket controlling nuget resolution
And as an aside, I really must commend you for your rapid response time. You really maintain this package well and it is quite nice dealing with you :)
Many package authors made the mistake of omitting the brackets, effectively specifying >= 1.2.3 when they wanted to specify = 1.2.3
This is the default when installing a package via NuGet. I didn't even know about the version ranges. I think a major version range should be ok.
And as an aside, I really must commend you for your rapid response time. You really maintain this package well and it is quite nice dealing with you :)
Thanks! I'm not always this responsive. It really depends on many life factors. ;)
I agree that a major range should normally be good enough. as for the responsiveness, very understandable, I guess I've just been lucky :) At any rate, your support is much appreciated!
I should probably specify a specific version with brackets. That will ensure it always works, correct?
well, it locks that specific version of the dependency, which is generally a good thing in my opinion because that is the version that you used and tested. Until it is either no longer available, has a security issue or you need to update for other reasons, I think locking to specific versions is in fact preferable. The exception to this rule would be in the case of dependencies that you control directly, in which case, you know what you are doing and may want your downstreams to automatically take the latest at all times etc. but generally, yes, locking a specific version or small sub-range would probably be a better approach, certainly a more deterministic one where package resolution is concerned.
I changed all the references to exact version match. Between that and redirects, I think we should be good.
When using V15.0.0.6 when I compile a release package it doesn't work on the deployed server and gives
System.Io.FileNotFoundException: Could not load file or assembly 'Microsoft.bcl.AsyncInterfaces, V1.0.0.0'
works fine on local instance of Visual Studio. If I downgrade to version 12.3.2 everything works fine. From my perspective the latest versions of CsvHelper don't support production use because of the compilation bug
To Reproduce Steps to reproduce the behavior: