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

Consuming v2 on .NET Framework 4.6.2 #1001

Closed
joaocpaiva opened this issue Nov 13, 2018 · 25 comments
Closed

Consuming v2 on .NET Framework 4.6.2 #1001

joaocpaiva opened this issue Nov 13, 2018 · 25 comments

Comments

@joaocpaiva
Copy link

Hi there,

We are trying to update to StackExchange.Redis v2 but I found v2 carries over a few dependencies built off .NET Standard 2.0 (listed below). There are some known runtime issues when using .NET Standard 2.0 assemblies with .NET Framework 4.6.2 outlined here due to missing APIs and issues with binding redirects. I wonder if you guys are aware of any of these issues affecting consumers running on .NET 4.6.2 and if you have a recommendation on how to proceed?

We don't want to take the risk of moving to v2 to only find issues when we get to production because of edge cases that we were not able to catch before.

netstandard2.0\System.Buffers.dll
netstandard2.0\System.IO.Pipelines.dll
netstandard2.0\System.Memory.dll
netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
netstandard2.0\System.Threading.Channels.dll
netstandard2.0\System.Threading.Tasks.Extensions.dll
@mgravell
Copy link
Collaborator

the main answer I have for this is simply:

image

I'm not aware of any outstanding specific conflicts here.

@joaocpaiva
Copy link
Author

@mgravell I am getting this error at runtime.
[System.InvalidOperationException: The assembly for System.Buffers and System.IO.Pipelines could not be loaded; this usually means a missing assembly binding redirect - try checking this, and adding any that are missing; note that it is not always possible to add this redirects - for example 'azure functions v1'; it looks like you may need to use 'azure functions v2' for that - sorry, but that's out of our control;

Unfortunately I am not able to repro this locally so it's a little harder to debug. Do you know what binding redirects I might be missing? Is this happening because the process is finding more than 1 assembly for those two namespaces? I am not sure why I am not repro'ing this locally though.

@joaocpaiva
Copy link
Author

And I don't have any binding redirect issues at compile time, it's only at runtime in the cloud VMs. Any ideas on how to debug this further? I will try to remote to the VM tomorrow so any tips are welcome.

@mgravell
Copy link
Collaborator

mgravell commented Nov 15, 2018 via email

@joaocpaiva
Copy link
Author

Running the latest, 2.0.513.

@mebjas
Copy link

mebjas commented Nov 22, 2018

What is the status of this? I am getting this in .Net Framework 4.7 as well.
Library Version: 2.0.513

@mgravell
Copy link
Collaborator

Status: needs attention - will try to look ASAP

@Krashlog
Copy link

We're having the same log on .Net Framework 4.7.2 (client 2.0.513)

@joaocpaiva
Copy link
Author

      Status: needs attention - will try to look ASAP

This error fixed for me after applying all fixes for conflicts and binding redirect warnings listed by msbuild (/Visual Studio). Unfortunately mixing .NET Standard 2.0 and .NET Framework 4.6x brings a ton of compatibility issues.

@ttworld01
Copy link

      Status: needs attention - will try to look ASAP

This error fixed for me after applying all fixes for conflicts and binding redirect warnings listed by msbuild (/Visual Studio). Unfortunately mixing .NET Standard 2.0 and .NET Framework 4.6x brings a ton of compatibility issues.

I find the same problems too. Have you solve them?

@mgravell
Copy link
Collaborator

mgravell commented Dec 3, 2018

Unfortunately mixing .NET Standard 2.0 and .NET Framework 4.6x brings a ton of compatibility issues.

We have a dedicated net461 build, which should be what you're consuming here. But yes; there are some things that MS screwed up with assembly binding at this level.

@joudot
Copy link

joudot commented Jan 10, 2019

Same issue with the version 519.

I wrapped StackExchange.Redis in a .NET Standard 2.0.3 or .NET 4.6.1 library.

While trying to import it from a .NET 4.6.1 test project, I see the InvalidOperationException saying System.Buffers could not be loaded. No matter if I import the .NET Standard 2.0.3 or .NET 4.6.1 version of my library, I see the error at runtime.

@mebjas
Copy link

mebjas commented Jan 10, 2019 via email

@MZar2019
Copy link

MZar2019 commented Jul 3, 2019

We had the same error/issue: "The assembly for System.Buffers could not be loaded; this usually means a missing assembly binding redirect..." and it took several days of trial and error to find a solution, so, this might help someone here.

Our IDE is Visual Studio 2019 16.1 4, our new Redis library that uses StackExchange.Redis is .NET Standard 2.0 and the projects that use the Redis library are many years old and were originally much older versions of .NET Framework, but had been changed to 4.7.2 to build with the new .NET Standard 2.0 libraries (as recommended by Microsoft).

This process resolved our dependency issues:

  1. Create a new .NET Framework 4.7.2 project
  2. Move all the existing source code into the new project
  3. Re-add, only those required to build/run, assembly and project references
  4. (Nuget) Add StackExchange.Redis (2.0.601)
  5. (Nuget) Downgrade System.Runtime.CompilerServices.Unsafe to 4.5.1

Note: StackExchange.Redis also gets downgraded to 2.0.519

Best regards,
Mike Zarlenga

@MZar2019
Copy link

MZar2019 commented Jul 8, 2019

Damn! The same exact code from my prior post (see above), when run on a different machine (W7 instead of Server 2016), complains:

Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1...

Updating the System.Runtime.CompilerServices.Unsafe nuget package to 4.5.2 resolves that, and it will run on W7, but it won't run on the Server 2016 test box.

We're now re-evaluating whether or not to use Redis, we can't afford unpredictable run-time errors like this and we can't test all possible o/s configurations.

Do the StackExchange developers understand what the problem is and are they working on a fix?

@mgravell
Copy link
Collaborator

mgravell commented Jul 8, 2019

Yes, the problem is the BCL packages have some borked bindings. The consumer can fix them with binding redirects. The borked bindings are fixed in the preview bits, from what I've seen. Hence adding a package-reference to the preview version of System.Runtime.CompilerServices.Unsafe from nuget may be a viable immediate fix. Well will update to the a versions with the fix as soon as they are released, but: it isn't our DLLs that are borked here - it is Microsoft's

@MZar2019
Copy link

MZar2019 commented Jul 8, 2019

Thank you for the response, Marc.

Updating just the .Unsafe package to the prerelease version (4.6.0-preview6.19303.8) did not resolve the problems with dependencies. We also tried updating all the other updatable packages to their highest release versions, but that did not work either.

You mention that we can fix this with binding redirects. I'm not familiar with that topic or process. Can you point me to what you think is a good link for explaining the way binding redirects work and the best ways to implement them?

Thank you.

@emilbm
Copy link

emilbm commented Jul 15, 2019

[System.InvalidOperationException: The assembly for System.Buffers and System.IO.Pipelines could not be loaded; this usually means a missing assembly binding redirect - try checking this, and adding any that are missing; note that it is not always possible to add this redirects - for example 'azure functions v1'; it looks like you may need to use 'azure functions v2' for that - sorry, but that's out of our control;

Regarding this error message from Redis: It's actually quite possible to do code-based binding redirects to make it compatible for V1-Functions. You can even put it in an Azure Setting as JSON so you don't have to hardcode it. I'll explain my solution to this issue below, but this was just mainly to let people know that error message does not mean you HAVE to upgrade to v2, which can be a real showstopper with its CORE-only approach.

Using that approach, I managed to get my Azure Functions V1 up and running using these versions (some of which are preview):

  • V1 Azure Functions
  • 4.6.1 Framework
  • 2.0.6001 StackExchange.Redis
  • 4.5.3 System.Memory
  • 4.5.0 System.Buffers
  • 4.0.5 System.Runtime.CompilerServices.Unsafe
  • 4.0.1 System.IO.Pipelines
  • 4.2.1 System.Threading.Tasks.Extensions

For the code-based-redirects, this is a simple version that hardcodes the redirects, but can easily be made reading a JSON string from settings. You can call FunctionAssemblyBindingRedirectHelper.ConfigureBindingRedirects() from your function initialization code, or just through a static constructor in your Function.cs.

public static class FunctionAssemblyBindingRedirectHelper
    {
        public static void ConfigureBindingRedirects()
        {
            var redirects = GetBindingRedirects();
            redirects.ForEach(RedirectAssembly);
        }

        private static List<BindingRedirect> GetBindingRedirects()
        {
            var result = new List<BindingRedirect>() {
                new BindingRedirect() { ShortName = "System.IO.Pipelines", PublicKeyToken = "cc7b13ffcd2ddd51", RedirectToVersion = "4.0.1.0"},
                new BindingRedirect() { ShortName = "System.Threading.Tasks.Extensions", PublicKeyToken = "cc7b13ffcd2ddd51", RedirectToVersion = "4.2.1.0"},
                new BindingRedirect() { ShortName = "System.Memory", PublicKeyToken = "cc7b13ffcd2ddd51", RedirectToVersion = "4.0.1.1"},
                new BindingRedirect() { ShortName = "System.Buffers", PublicKeyToken = "cc7b13ffcd2ddd51", RedirectToVersion = "4.0.3.0"},
                new BindingRedirect() { ShortName = "System.Runtime.CompilerServices.Unsafe", PublicKeyToken = "b03f5f7f11d50a3a", RedirectToVersion = "4.0.5.0"}
            };

            return result;
        }

        private static void RedirectAssembly(BindingRedirect bindingRedirect)
        {
            ResolveEventHandler handler = null;
            handler = (sender, args) =>
            {
                var requestedAssembly = new AssemblyName(args.Name);
                if (requestedAssembly.Name != bindingRedirect.ShortName)
                {
                    return null;
                }
                var targetPublicKeyToken = new AssemblyName("x, PublicKeyToken=" + bindingRedirect.PublicKeyToken).GetPublicKeyToken();
                requestedAssembly.SetPublicKeyToken(targetPublicKeyToken);
                requestedAssembly.Version = new Version(bindingRedirect.RedirectToVersion);
                requestedAssembly.CultureInfo = CultureInfo.InvariantCulture;
                AppDomain.CurrentDomain.AssemblyResolve -= handler;
                return Assembly.Load(requestedAssembly);
            };
            AppDomain.CurrentDomain.AssemblyResolve += handler;

        }

        public class BindingRedirect
        {
            public string ShortName { get; set; }
            public string PublicKeyToken { get; set; }
            public string RedirectToVersion { get; set; }
        }
    }

@viniciusvillas
Copy link

viniciusvillas commented Aug 16, 2019

it isn't our DLLs that are borked here - it is Microsoft's

Every other package in our solution works as expected. StackExchange.Redis is the only one giving us trouble. Kinda hard to put this one on MS' back. Just saying.

@mgravell
Copy link
Collaborator

@viniciusvillas and yet it is true; I've had extensive conversations with Microsoft about this issue; it is well known

@yuzhangyi
Copy link

yuzhangyi commented Sep 26, 2019

@mgravell, is the up problem solved now? In our PROD, we also meet this problem.
Error:
System.InvalidOperationException: The assembly for System.Buffers could not be loaded; this usually means a missing assembly binding redirect - try checking this, and adding any that are missing; note that it is not always possible to add this redirects

StackExchange.Redis.2.0.519\lib\net461\StackExchange.Redis.dll

Dependency:

  • System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll
  • System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll
  • System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll
  • Pipelines.Sockets.Unofficial.1.0.7\lib\net461\Pipelines.Sockets.Unofficial.dll
  • System.Diagnostics.PerformanceCounter.4.5.0\lib\net461\System.Diagnostics.PerformanceCounter.dll
  • System.IO.Pipelines.4.5.1\lib\netstandard2.0\System.IO.Pipelines.dll
  • System.Threading.Channels.4.5.0\lib\netstandard2.0\System.Threading.Channels.dll

@toebens
Copy link

toebens commented Oct 8, 2019

we are having some problems with sgen on .net 4.7.2 in Release build dotnet/msbuild#2707
only setting GenerateSerializationAssemblies off seems to help

Is there anything or another workaround we can do about it @mgravell ?

@Kevin-Skeepers
Copy link

I've been struggling with this for multiple days, as I'm updating most packages for our web app.

First struggle, was with the StrongName mess, which had to be removed and switched to the real Redis package so I could upgrade the version.
Then with other Redis packages, notably the SignalR AspNet one which was still using the StrongName package internally which would create a reference mismatch. Had to use a new obscure Microsoft.AspNet.SignalR.StackExchangeRedis package to replace the former.

And now finally I get this crazy System.Memory error at runtime, requiring version 4.0.1.0.
What the hell guys, we are almost in 2020. It's time to fix this.

We are using .NET 4.6.2
StackExchange.Redis 2.0.601
Microsoft.AspNet.SignalR.StackExchangeRedis 2.4.1
Microsoft.Web.RedisOutputCacheProvider 3.0.1
Microsoft.Web.RedisSessionStateProvider 4.0.1

'Could not load file or assembly 'System.Memory, Version=4.0.1.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)'

@uuggene
Copy link

uuggene commented Jan 12, 2020

I managed to run it with following assembly binding redirects in web.config (I needed to downgrade System.IO.Pipelines to 4.0.0.1):
<dependentAssembly> <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.IO.Pipelines" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.0.1" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Threading.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" /> </dependentAssembly>
Part of packages.config
<package id="Microsoft.Web.RedisSessionStateProvider" version="4.0.1" targetFramework="net462" /> <package id="Pipelines.Sockets.Unofficial" version="2.1.1" targetFramework="net462" /> <package id="StackExchange.Redis" version="2.0.601" targetFramework="net461" /> <package id="System.Buffers" version="4.5.0" targetFramework="net462" /> <package id="System.IO.Pipelines" version="4.7.0" targetFramework="net462" /> <package id="System.Memory" version="4.5.3" targetFramework="net462" /> <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.7.0" targetFramework="net462" /> <package id="System.Threading.Channels" version="4.7.0" targetFramework="net462" /> <package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net462" />

@NickCraver
Copy link
Collaborator

I've written up the background, why it happens, and how to fix this at: https://nickcraver.com/blog/2020/02/11/binding-redirects/ (it's an issue we've seen across the ecosystem for years). I hope this helps anyone running into the issue - going to close out here since it's not specific to SE.Redis at all and the fix is more general. Check out the above blog post (not a long read) for a few options to resolve it.

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

No branches or pull requests