Hi,
I was wondering if there is a reason why there is no restriction (upper limit/range limit) on the Microsoft.Extensions NuGet packages? Due to the lack of restriction, it is possible for anyone to just add an explicit NuGet package reference to their project. Given that NuGet implements "nearest wins" (https://docs.microsoft.com/en-us/nuget/concepts/dependency-resolution#nearest-wins) as a resolution strategy, and you can only have a single version of any package per project it will resolve to the explicit reference, overriding any downstream reference resulting in these MissingMethodException issues.
By setting an limit for the package version, the NuGet package reference system will detect that the reference cannot not be resolved and it will give you a compile time warning, instead of a runtime exception, which should be preferable at all times.
A simple example would be the following:
Project A
-> package reference Microsoft.Extensions.Logging.Console 3.1.0
-> project reference B
Project B
-> package reference Microsoft.Extensions.Logging 2.2.0
This will produce runtime exceptions when the Microsoft.Extensions.Logging.Console logger (3.1.0) tries to call methods that do not exist in Microsoft.Extensions.Logging (2.2.0).
@DamianEdwards ?
Best practice is to avoid doing this: https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/dependencies#nuget-dependency-version-ranges
This seems similar to https://github.com/dotnet/aspnetcore/issues/25305
Best practice is to avoid doing this: https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/dependencies#nuget-dependency-version-ranges
Could you elaborate as to why you should avoid this and what an alternative would be to prevent runtime issues?
There is no general solution to this.
When you have 2 projects/packages referencing different major versions, we will hoist to the highest version when unconstrained. And because there can be breaking changes between major versions there is no guarantee that the lower versioned package will continue to work.
What are project A and project B in your example?
@BrennanConroy I am aware that there is no general solution for this. I was specifically wondering why the Microsoft.Extensions packages do not set an upper limit, as this would yield a compile time error instead of a runtime error. It seems odd to allow you to target a different major version as best practice when the versioning scheme indicates that there are guaranteed breaking changes?
In my example, project A is a customer project, and project B is our library code which is packaged with Microsoft.Extensions.Logging.
In the referenced ticket the issue I hit was that packages built by Microsoft had this issue and my complete stack resulted in collisions in Microsoft provided dependencies.
In my opinion the fix here should be to use the latest minor based on the major version referenced at the most "root" part of the compilation stack.
To put it how @bartbovendeerdt puts it ...
Project A
-> package reference Microsoft.Extensions.Logging.Console 3.1.0
-> project reference B
Project B
-> package reference Microsoft.Extensions.Logging 2.2.0
If Project A references "Microsoft.Extensions.Logging" then the version referenced there should be honoured for the complete compile and used in all projects that Project A depends on. This doesn't appear to always work though due to internal restrictions at the package level from what I understand causing the linked issue I have.
My understanding is that I as the stack developer should have an idea of what I am trying to achieve and should therefore be able to somehow state to the build process / compiler "when you see this package anywhere use this version".
I get the feeling that's not possible but something tells me I am missing a piece of this complex puzzle somewhere.
.Net still has binding redirection in the xml .config file but I don't think .Net Core honours that.
Edit: To be clear ...
If "Microsoft.Extensions.Logging.Console 3.1.0" depends on ta different Major version I would argue that this should be a compile time error and the Developer be given clear instruction to the effect of "Directly reference the major version of Microsoft.Extensions.Logging that you wish the stack to use to resolve this".
It's a bit forceful but it's effect is that the Developer is making a choice that compatible versions of dependencies "determined by major version by the Developer" and by extension their dependencies should be either implicitly correct or explicitly correct as a fall back rule that should always be honoured.
Most helpful comment
@DamianEdwards ?