Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microsoft.Bcl.AsyncInterfaces missing for netcoreapp3.1 #823

Closed
AbeniMatteo opened this issue Jun 14, 2020 · 43 comments
Closed

Microsoft.Bcl.AsyncInterfaces missing for netcoreapp3.1 #823

AbeniMatteo opened this issue Jun 14, 2020 · 43 comments
Labels

Comments

@AbeniMatteo
Copy link

AbeniMatteo commented Jun 14, 2020

Version

5.0.0

Expected behavior

No expection.

Actual behavior

Exception thrown:

An unhandled exception of type 'System.IO.FileNotFoundException' occurred in repro.dll
Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.

To Reproduce

repro.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="SimpleInjector" Version="5.0.0" />
  </ItemGroup>
</Project>

program.cs

namespace repro
{
    static class Program
    {
        static void Main() => LoadSimpleInjector();
        static void LoadSimpleInjector() => new SimpleInjector.Container();
    }
}

Additional context

For .NET Core apps, IAsyncDisposable is declared in System.Runtime.dll and Microsoft.Bcl.AsyncInterfaces is also not listed as a Nuget package dependency.

@dotnetjunkie
Copy link
Collaborator

Crap! I'm able to reproduce this issue. Not sure yet what goes wrong here. The NuGet references MS.Bcl.AsyncInterfaces in the 4.6.1 and .NETStandard2.0 targets. The reference is omitted in .NETStandard2.1 because the interface is part of .NETStandard2.1. But perhaps the version compiled for 2.1 contains a hard-referenece to MS.Bcl.AsyncInterfaces. I wil investigate and push a patch release.

In the meantime, you can work around the issue by adding MS.Bcl.AsyncInterfaces to your project as NuGet package.

@dotnetjunkie
Copy link
Collaborator

dotnetjunkie commented Jun 15, 2020

Problem found: the /lib/netstandard2.1/SimpleInjector.dll was missing from the NuGet package. This caused NuGet to revert to the /lib/netstandard2.0/SimpleInjector.dll, while still using the .NET Standard 2.1 configuration, which didn't include Microsoft.Bcl.AsyncInterfaces.

I pushed Simple Injector 5.0.1 to NuGet that fixes this problem.

@michaelkhalsa
Copy link

Hi,
App: Win Forms using .Net Framework 4.8
Installer: Microsoft VS Desktop Installer build .98
VS : 2019 Latest (not preview)

Build 5.01 (upgraded from build 4.1) broke my application (this took several days to find what was going on, as did not suspect simple injector). And adding a ref to nuget for this assembly does not work (I did not try an assembly redirect, and i believe i turned off this option).

It looks like Simple Injector contains a reference to 1.0.0 for Microsoft.Bcl.AsyncInterfaces
It will build fine and run within VS, however when installed, it crashes on startup with an error: reference assembly should only be loaded through reflection error.

I believe the solution is to use version 1.1.0 or 1.1.1 via nuget, as quite a few libraries do (such as csv helper, reactive, etc) within your library, instead of including a gac assembly in your library.

Downgrading back to simple injector 4.1 fixed the problem
This took several days of work to figure out.
Once i narrowed it down to Simple Injector as the culprit, I looked in the project assets.json file in the obj folder for the main windows project to go through all of the assemblies using the Bcl.AsyncInterfaces, and found that build 5.01 was indeed referencing 1.0.0 assembly. When i downgraded, the ref to any BCL assembly was gone from Simple Injector.

Several other libraries which are using version 1.1.0 work fine.

@dotnetjunkie
Copy link
Collaborator

Hi Michael,

A NuGet package should always use the lowest possible version of a dependency, which is why Simple Injector referwnces 1.0 of AsyncInterdaces. This generally means that binding redirects need to be used (under .NET) and NuGet typically managescthat for you. I say typically, because NuGet tends to fuck up from time to time.

But the solution is to manually add the binding redirect in case NuGet fails to do so.

@michaelkhalsa
Copy link

michaelkhalsa commented Jun 21, 2020 via email

@dotnetjunkie
Copy link
Collaborator

dotnetjunkie commented Jun 21, 2020

I am not sure if you are including the actual assembly in the package, but the error makes it sound like that?

No, no other dlls are included except the SimpleInjector.dll itself. The only thing the SimpleInjector.nupkg does is reference the other Nuget packages.

I'm very sorry you are running into this. It is for this exact reason that the Simple Injector core library never had any dependencies. You quickly run into binding redirect issues, and NuGet often fails to generate correct binding redirects for you.

Unfortunately, with The new IAsyncDisposable, there is no good way around this. You will have to add the binding redirect. Upgrading the package dependency might fix the problem for you, but is only a transient fix, because it will still cause problems for others and when never versions of AsyncInterfaces is pushed, as long as you don't use binding redirects under .NET Framework.

@michaelkhalsa
Copy link

Hi Steven,

I will circle around to this in a couple days, by creating a small test app, and see what works or not.

Including what happens when another library is present that is referencing version 1.1+ of Microsoft.BCL.AsyncInterfaces, along with Simple Injector 5.01

As well as revisit using an assembly redirection

Again, where it fails, is after installing the app with Microsoft Visual Studio Package Installer (upon startup), not after F5 build. So will test in that environment, to confirm the behavior in a limited small app.

On another note, you may want to contact the developers of the following libraries, to learn from their approach. All of these use Microsoft.BCL.AsyncInterfaces Ver 1.1.0

  • System.Reactive
  • CsvHelper
  • Stripe.Net

Thanks, and will let you know if I find anything of value.

image

@dotnetjunkie
Copy link
Collaborator

dotnetjunkie commented Jun 22, 2020

You can add the following binding redirect to fix the problem:

  <?xml version="1.0" encoding="utf-8"?>
  <configuration>
    <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
          <assemblyIdentity
              name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" 
              culture="neutral" />
          <bindingRedirect oldVersion="0.0.0.0-{your-version}" newVersion="{your-version}"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity
              name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" 
              culture="neutral" />
          <bindingRedirect oldVersion="0.0.0.0-{your-version}" newVersion="{your-version}"/>
        </dependentAssembly>
      </assemblyBinding>
    </runtime>
  </configuration>

Where {your-version} is the (highest) version you installed. Please note that you need to add the binding redirects for both Microsoft.Bcl.AsyncInterfaces and for System.Threading.Tasks.Extensions. For instance:

  • Using Microsoft.Bcl.AsyncInterfaces 1.1.0:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity
                name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" 
                culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity
                name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" 
                culture="neutral" />
            <!-- The 4.5.2 NuGet package contains an assembly with version 4.2.0.0 -->
            <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
  • Using Microsoft.Bcl.AsyncInterfaces 1.1.1:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity
                name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" 
                culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity
                name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" 
                culture="neutral" />
            <!-- The 4.5.4 NuGet package contains an assembly with version 4.2.0.1 -->
            <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
  • Using Microsoft.Bcl.AsyncInterfaces 5.0.0:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <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>
          <dependentAssembly>
            <assemblyIdentity
                name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" 
                culture="neutral" />
            <!-- The 4.5.4 NuGet package contains an assembly with version 4.2.0.1 -->
            <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

@andrejohansson
Copy link

andrejohansson commented Nov 12, 2020

I'm also hitting this problem and for me, binding redirects doesn't help. I cannot seem to figure out why.

I have the following setup

CodelockFunctionsNET (.net 461 target)
  -> BokaMera.Api.CodeLock.Model (netstandard2.0 target)
    -> Microsoft.Extensions.Logging 5.0.0
      -> Microsoft.Bcl.AsyncInterfaces
    -> SimpleInjector 5.1.0
      -> Microsoft.Bcl.AsyncInterfaces

I have tried a lot back and forth without any success. I get:

mscorlib: Exception while executing function: VanderbiltOmnis. CodeLockFunctionsNET: The type initializer for 'CodeLockFunctionsNET.DIConfig' threw an exception. CodeLockFunctionsNET: Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.

I have tried assembly redirects both via app.config and via setting

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

In both my projects: CodelockFunctionsNET and BokaMera.Api.CodeLock.Model.
When I look in my bin\Debug\net461 folder I find the generated binding redirects correctly:

image

image

Also the file is present and is v5.0.0.0
image

Then I start the project using func host start (this is a Azure Function v1), and as soon as it should load SimpleInjector I get the exception.

Not that ILogger from Microsoft.Extensions.Logging who also uses Microsoft.Bcl.AsyncInterfaces can be present and works.

Commenting out all SimpleInjector code makes the code run without exceptions.

So...something is fishy here still unfortunately, it´s like the redirect is not respected at all?

Any suggestions of how I can proceed?

@andrejohansson
Copy link

Follow up: Apparently, binding redirects does not exist on Azure functions! But the solution presented in this article seems to work for me: https://www.thewissen.io/azure-functions-binding-redirects/

@AceVentura
Copy link

Hello,

I'm having the same issue with .net core 3.1.10.
Project Type: Xunit.
SimpleInjector 5.1.0
SimpleInjector.Integration.ServiceCollection 5.0.2

@dotnetjunkie
Copy link
Collaborator

@AceVentura this update should help. You likely need to add both AsyncInterfaces and and System.Threading.Tasks.Extensions to your binding redirects (and possibly even System.Runtime.CompilerServices.Unsafe).

@AceVentura
Copy link

@dotnetjunkie I'm on .net core. As far as I know, there are no such thing as binding redirects here..

@dotnetjunkie
Copy link
Collaborator

@AceVenture. Yes, what I understood is that binding redirects are not an issue any longer on .NET Core. So, what isnyoyr issue exactly? Do you have an exception message with stack trace? A bit more information would be helpful.

@AceVentura
Copy link

AceVentura commented Nov 19, 2020

@dotnetjunkie the error happens when I call this:

IServiceProvider provider =
    SimpleInjectorServiceCollectionExtensions.AddSimpleInjector(services, _container).
        BuildServiceProvider(validateScopes: true);

Exception+ Stack Trace:

System.IO.FileNotFoundException: 'Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.'

at SimpleInjector.SimpleInjectorServiceCollectionExtensions.AddContainerDisposalOnShutdown(IServiceCollection services, SimpleInjectorAddOptions options)
at SimpleInjector.SimpleInjectorServiceCollectionExtensions.AddSimpleInjector(IServiceCollection services, Container container, Action`1 setupAction)
at Nexllence.ANF.B2C.Tests.BaseTestClass..ctor() in C:\projects\it07010120a0829-servicos-de-implementacao-b2c\Nexllence.ANF.B2C.Tests\BaseTestClass.cs:line 76
at Nexllence.ANF.B2C.Tests.Business.ConfigurationBcTests..ctor() in C:\projects\it07010120a0829-servicos-de-implementacao-b2c\Nexllence.ANF.B2C.Tests\Business\ConfigurationBcTests.cs:line 12

Note: This only happens in the xunit project. The WebApi project is working without issues.
I have a similar project, with the only difference being that it's using Simple Injector 4.9.0 and this issue never showed up.

@dotnetjunkie
Copy link
Collaborator

I have a similar project, with the only difference being that it's using Simple Injector 4.9.0 and this issue never showed up.

That's because the dependency with the Microsoft.Bcl.AsyncInterfaces NuGet package was added in Simple Injector v5. The Simple Injector v4 core library does not have any dependencies.

Did you try adding the Microsoft.Bcl.AsyncInterfaces explicitly to your xunit project?

@AceVentura
Copy link

I have not, because the package says it's not needed:
Provides the IAsyncEnumerable<T> and IAsyncDisposable interfaces and helper types for .NET Standard 2.0. This package is not required starting with .NET Standard 2.1 and .NET Core 3.0.

@dotnetjunkie
Copy link
Collaborator

Would you mind trying it anyway? We're in NuGet land here. Things get murky sometimes.

Also, can you check at runtime, which assemblies (exact version number) the following types live in:

  • IAsyncDisposable
  • ValueTask

You can do this, for instance, by adding a unit test that does the following:

Assert.Fail(typeof(IAsyncDisposable).Assembly.FullName + " " +
    typeof(ValueTask).Assembly.FullName);

@AceVentura
Copy link

@dotnetjunkie with the package it does work yes.
As for the the assemblies:
System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e

@dotnetjunkie
Copy link
Collaborator

@dotnetjunkie with the package it does work yes.

I have had this myself with other packages in the past, so I know that adding packages to the startup project (in your case the xunit project) helps. Don't ask me why, though. Not sure what's going on under the covers.

That said, the addition of the AsyncInterfaces assembly to the core library gave a lot of trouble. Unfortunately, as I discussed in #867, I haven't found a good way to circumvent these issues.

@AceVentura
Copy link

As I suggestion, I would put a warning somewhere in the documentation about this error. Or worst case scenario, make it a required dependency.

@dotnetjunkie
Copy link
Collaborator

The dependency is already required. Nothing we can do in that respect.

@AceVentura
Copy link

Maybe increase it to the V5? (It's the one I installed). That may be the culprit

@dotnetjunkie
Copy link
Collaborator

That will unfortunately not work, because a dependency on v5 might cause problems with users of .NET Core v3, and even if it works, it will only temporary solve the problem, untill the moment that Microsoft comes with newer versions of these packages. In that case, the dependency hell starts all over again.

@dotnetjunkie
Copy link
Collaborator

Hi @AbeniMatteo, @andrejohansson, @AceVentura,

I pushed an 5.2.0-alpha2 version of the Simple Injector core library and the ASP.NET Core integration packages to NuGet. These set of packages tend to solve the problems regarding Microsoft.bcl.AsyncInterfaces completely. Would you mind trying these packages out to see if this solves the problem for you and whether there are any unintended consequences? Your feedback is very welcome, and it would be great if you would try this out on your actual applications (not in production of course ;-), because in order to get this all working, quite some changes were required. Of course I did my own testing, but I really need more proof before I dare pushing this fix as RTM to NuGet.

You can see more details about what changes here: #867. This is also the place to post any feedback.

Thanks in advance

@AceVentura
Copy link

Hey @dotnetjunkie, I only managed to test it today. Removed Microsoft.bcl.AsyncInterfaces and tested with 5.2.0-alpha2 and 5.2.0. The error is the same as before.

@dotnetjunkie
Copy link
Collaborator

@AceVentura, that's very unfortunate. Fortunately, Simple Injector is not part of the Diamond Dependency Conflict any longer. Please review your solution's dependency chains. Your application is likely using multiple packages that reference different versions of either:

  • Microsoft.Bcl.AsyncInterfaces
  • System.Threading.Tasks.Extensions
  • System.Runtime.CompilerServices.Unsafe

Here are some packages that I know take a dependency on one of the above:

  • System.Memory
  • System.Collections.Immutable
  • Microsoft.Extensions.DependencyInjection
  • Microsoft.AspNetCore.Mvc.Core
  • System.Text.Json

See if you can either remove those packages. In some cases (e.g. with Microsoft.AspNetCore.Mvc.Core or Microsoft.AspNetCore.Mvc.Core) you will certainly be stuck with those dependencies and there's not much you can do about it.

Instead, you can try the following:

  • Make sure all projects in the solution depend on the same version of a used package (by right-clicking on the solution node in the Solution Explorer, selecting "Manage NuGet Packages for solution..." and selecting the "Consolidate" tab.
  • Than add all three packages (AsyncInterfaces, Tasks.Extensions, and CompilerServices.Unsafe) explicitly to your startup projects. This will (hopefully) ensure NuGet to add the correct binding redirects. Remember: NuGet might add binding redirects to a project that has a package installed, but binding redirects only have effect on startup projects.

I hope this helps.

@Lukiya
Copy link

Lukiya commented Dec 28, 2020

Hi @AbeniMatteo, @andrejohansson, @AceVentura,

I pushed an 5.2.0-alpha2 version of the Simple Injector core library and the ASP.NET Core integration packages to NuGet. These set of packages tend to solve the problems regarding Microsoft.bcl.AsyncInterfaces completely. Would you mind trying these packages out to see if this solves the problem for you and whether there are any unintended consequences? Your feedback is very welcome, and it would be great if you would try this out on your actual applications (not in production of course ;-), because in order to get this all working, quite some changes were required. Of course I did my own testing, but I really need more proof before I dare pushing this fix as RTM to NuGet.

You can see more details about what changes here: #867. This is also the place to post any feedback.

Thanks in advance

I confirm this issue solved by updated SimpleInjector.Integration.AspNetCore.Mvc to 5.2.0-alpha2.

@dotnetjunkie
Copy link
Collaborator

Thanks for the feedback @Lukiya, much appreciated.

@AbeniMatteo
Copy link
Author

@dotnetjunkie SimpleInjector@5.2.0-alpha2 on net5.0-windows works fine for me.

@dotnetjunkie
Copy link
Collaborator

@AbeniMatteo, awesome. Thanks 👍

@pampua84
Copy link

Hi i have the same problem in my razor pages project in net5.0. Approximately when will the alpha package be released as a stable version?

@dotnetjunkie
Copy link
Collaborator

Approximately when will the alpha package be released as a stable version?

Approximately 44 days ago.

@pampua84
Copy link

Sorry I didn't see it because I directly installed SimpleInjector.Integration.AspNetCore.Mvc 5.1.1 which doesn't depend on the new version. Sorry

@dotnetjunkie
Copy link
Collaborator

No problem @pampua84. If you upgrade to SimpleInjector.Integration.AspNetCore.Mvc 5.2, you'll get SimpleInjector-5.2 as well. But I advise you to explicily install the Simple Injector core library as well in your project and upgrade that to 5.2.1, as it contains an important bug fix.

@gedeh
Copy link

gedeh commented Feb 18, 2021

Heya, just updated my ASP.NET Web API project .NET 5, and I see this issue. I try to use version 5.2.0 but seems https://www.nuget.org/packages/SimpleInjector.Integration.AspNetCore.Mvc in nuget is still at v5.1.1 :)

Although good things, this makes me realize that I dont use Razor pages so I use https://www.nuget.org/packages/SimpleInjector.Integration.AspNetCore.Mvc.Core instead.

Thanks!

@dotnetjunkie
Copy link
Collaborator

Hi @gedeh , thank you for reporting this. Something apparently went silently wrong during uploading the packages. Either at my side, or at NuGet's side. I'll try to upload the missing packages a.s.a.p.

@dotnetjunkie
Copy link
Collaborator

@gedeh, the package is now waiting to be indexed by Nuget. Will be available soon.

@gedeh
Copy link

gedeh commented Feb 18, 2021

That was blazing fast @dotnetjunkie! See it in NuGet now, wow!

@vutung3196
Copy link

vutung3196 commented Mar 1, 2021

I'm having this issue with .NET 5, I use Autofac

@dotnetjunkie
Copy link
Collaborator

@vutung3196, this is the Simple Injector forum. We will not answer questions related to Autofac.

@vutung3196
Copy link

Yeah I see

@pablo-sage
Copy link

I know it's been more than a year since last answer, but.... I wanted to say something that could help and it's that, apparently, the order in which the <dependentAssembly> items appear in the .config file can make this error happen (though my case is a .net48 project, not a netcore one).

Hope it helps.

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

No branches or pull requests

10 participants