read 7 min
24 / 24
Sep 2024

It has been a while, and I haven’t tested it now, but I recall when a dependency became strong named (Polly???) I explicitly loaded the strong named version at start up (first statements of the application) and used AppDomain.AssemblyResolve Event to resolve references to the not strong named version.

Think of it as assembly binding redirect extended. :grinning:

The problem is that the code does not even compile. Signing an assembly generated completely different name. When My code needs to pass an instance of IMongoDatabase to a third party library you got compilation error because it cannot find the definition of IMongoDatabase unsigned.

https://jira.mongodb.org/browse/CSHARP-5206 for more reference, the problem is not binding redirect, it is the inability to even compile the code.

That happens when you are trying to reference both types (the strong named and the not strong named).

My “workaround” is for “fixing” the assembly binding.

I’m not referencing both types, I only reference the strongly typed one, but I use another nuget package that in turn reference the unsigned one. We know that we can perform assembly redirect via configuration file or other tricks, but the problem is the inability to compile, and that is the reason why it is always a bad practice to have a 10 years old library used by many and suddently add strongly typing :(.

Assembly redirect also is cited in the link above in this post, but we have a whole different problem, we needed to have a big bang update of all dependant libraries that uses old driver…

I’m not arguing the hassle of an assembly changing the string name (from null to something, in this case).

But you are having compile-time issues, because you are trying the use both. Otherwise, it would be a run-time issue for that library.

If you isolate the source code using one strong name from the other, you can explicitly load the assembly at startup and resolve the old assembly to the new one. You need code for that, because the assembly binding redirects configuration only redirects versions, not names and keys.

Actually if you are in this situation I’ve a simple github repository where I show how you can call the code through reflection

in .NET 6+ you can only use reflection and it will just work (Strongly Signed is not used anymore in .NET 6+)

In .NET 4.8 you still need to do some work to manually let referenced code to find the assembly since I was not able to fix this with only assembly redirect in App.Config (redirecting unsigned to signed seems not to work)

Assembly binding redirection only works on version number, not name or strong name.

With a breaking change this impactful, I’m surprised you didn’t bump the major version number (https://semver.org/). We had absolutely no warning. Updated the NuGet’s in our dotnet8 projects and boom! everything no longer compiles. This seems like very bad behavior for such a highly popular package.

13 days later

Is this a joke? We need to move to Atlas 8.0 as soon as it’s ready for operational use. This requires updating our driver to 2.29.0 once it’s released. We can’t wait for all our dependencies to update their MongoDB driver versions first.

Some libraries, such as MassTransit, have already updated to MongoDB driver version 2.28.0, which implies that this new version cannot be installed because the rest of the dependencies have not yet done so.

It is absurd to expect that all dependencies used in a project contain the same specific reference to another library.

We are quite surprised by this decision that blocks us and its implementation without notice. Please seriously reconsider removing this problem.

I would like to thank everyone for their input and personally apologize for the impact that adding a strong name to our assemblies has had on all of you. It was a unanimous decision from the .NET/C# Team here at MongoDB, to ship strong-named assemblies now and do so in 2.28.0 rather than 3.0.0. Mea culpa. Hopefully the explanation below provides some context.

The .NET/C# Driver 1.X releases were strong named. We removed strong naming with the release of the 2.0 Driver in 2015. We did this because of pain experienced by users with transitive dependencies and binding redirects. Soon after the release of 2.0, users started requesting strong named assemblies via CSHARP-1276. Although Microsoft no longer recommends strong names for applications, there is still a valid use case for libraries to be strong named. This is because some environments still require strong names such as SQL Server Integration Services, Microsoft Azure Data Factory, and others. Moreso, all .NET Core assemblies themselves are strong named for compatibility and serviceability.

So what have users requiring strong-named assemblies done for the past 9 years? Two community members went to the trouble of decompiling our assemblies, strong naming them, fixing up the inter-assembly references, relinking the assemblies, and building strong-named NuGet packages. They released unofficial strong-named packages such as MongoDB.Driver.signed. I would like to personally thank them for doing this for as long as they did. But for whatever reason they stopped publishing these strong-named packages with the 2.19.0 release. This left our strong-named users and partners without access to new features and bug fixes.

There are other 3rd party libraries like AspNetCore.Diagnostics.HealthChecks which have already been updated to the newer strong named version. Albeit painful, this is a one time change to be done. We understand the challenge with transitive dependencies and are open to reaching out to collaborate with other 3rd party open source developers to request them to update their MongoDB dependencies. Please let us know if we can help in doing so.

PS: MongoDB Atlas 8.0 does not necessarily need the driver version 2.29 and above, it will work with older versions of the driver as well. However, there are some capabilities that will be introduced in future versions of the driver like Range Indexes in v2.29 and Improved Bulk Write in v3.0 respectively.

It would be beneficial to continue to produce in the nuget package a .NET 5 version that is still not strongly typed. This because in .NET 5 and above, Strongly Named is not used anymore so you do not have any advantages, only problems.

At least everyone that is on .NET 5+ will be unaffected by the change. I know that this is more work for you, but actually it should be not very complicated to have two build. So you can produce .NET 4.8 signed .netstandard 2.0 signed, but .NET 5 unsiged

This will at least lessen the impact.

.NET 5 is long out of support and I wouldn’t target that for anything. Starting next November, .NET 8.0 and 9.0 will be the only supported runtimes.

As inconvenient as this is, the problem was created when strong naming was removed, not now. After a while, this will no longer be a problem.

Nevertheless, since the issue was caused by MongoDB, MongoDB should provide proper complete and correct guidance. And that could be a repo that users can build the driver from.

18 days later

A typical example. In our project we use GitHub - elsa-workflows/elsa-core: A .NET workflows library and uses mongodb extensions. We use Elsa 2 (moving to 3 has too much breaking changes). The version 2 is still using an old version of the driver.

Since we are extending some other classes, using reflection to call those extensions is literally a nightmare. Now we should hope that Elsa maintainer wants to patch an old version to support strongly type version of the driver. Elsa is a .NET core project so it does not benefit from strongly typed naming, but it is impacted too :(.

Trying to fork elsa mongodb support to upgrade driver does not works because it uses MongoDb.Bson.NodaTime that uses old driver. So I use a library, that uses a second library I fork that second library and I need to fork the third library, now I need to fork the fourth library … seriously … this is a nightmare.

You put us developer in an infinite hell of fork and a maintenance nightmare, even if in .NET core signed assembly is absolutely an unused feature…

I’m absolutely tired, the only solution is to stick to the older driver and probably never update because there are too many libraries that are old and not maintained and we need to fork an ecosystem.

Thanks for raising this. We’ve been working with maintainers like NServiceBus (recently merged a change to use the Strong Named driver) and Elsa (they’ve agreed to update both Elsa 2 and 3 to start using the Strong Named version of the MongoDB driver). I’d like to again thank all maintainers for making these updates and apologize for the inconvenience.

I do also want to share that updating beyond v2.27 is not necessary per say especially from a feature standpoint. Our focus is mainly on the next major version of the driver (v3.0.0) and all new features will be added in that version and beyond. The only anticipated 2.x releases we foresee are as follows:

  • v2.29.0 : Adds support for Range Indexes as GA which had been in preview previously
  • v2.30.0: Adds deprecations for the upcoming 3.0.0 release

I agree. It’s much easier to switch from MongoDB to another database provider than trying to update the entire OSS ecosystem. The last time I checked, there were around 1,500 NuGet packages that had dependencies on the MongoDB driver.

Breaking an ecosystem to support a deprecated / out of support framework is pure madness.