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

System.Configuration.ConfigurationManager package contains assemblies with inconsistent versions #77887

Closed
Alex-Sob opened this issue Nov 4, 2022 · 6 comments

Comments

@Alex-Sob
Copy link

Alex-Sob commented Nov 4, 2022

Description

System.Configuration.ConfigurationManager package v6.0.1 contains assemblies with inconsistent versions:

image

Particularly, this causes runtime issues in .NET Framework when a compiled project targeting netstandard2.0 references assembly version 6.0.0.0, but an assembly version 6.0.0.1 is used at runtime:

System.IO.FileLoadException: Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.

Reproduction Steps

Create library project that targets netstandard2.0 and references System.Configuration.ConfigurationManager 6.0.1 and run .NET Framework app that uses that library.

Expected behavior

No errors

Actual behavior

System.IO.FileLoadException

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 4, 2022
@ghost
Copy link

ghost commented Nov 4, 2022

Tagging subscribers to this area: @dotnet/area-system-configuration
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

System.Configuration.ConfigurationManager package contains assemblies with inconsistent versions:

image

Particularly, this causes runtime issues in .NET Framework when a compiled project targeting netstandard2.0 references assembly version 6.0.0.0, but an assembly version 6.0.0.1 is used at runtime:

System.IO.FileLoadException: Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.

Reproduction Steps

Create library project that targets netstandard2.0 and references System.Configuration.ConfigurationManager 6.0.1 and run .NET Framework app that uses that library.

Expected behavior

No errors

Actual behavior

System.IO.FileLoadException

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: Alex-Sob
Assignees: -
Labels:

area-System.Configuration, untriaged

Milestone: -

@joperezr
Copy link
Member

joperezr commented Nov 4, 2022

It is ok to have different versions (as long as you are not downgrading the version on a more concrete TFM) of the same assembly inside a NuGet package, even when the two different target frameworks for those different versions are compatible with each other (like in your case .NET Standard and .NET Framework).

The very likely reason why it is not working in your scenario, is because you are likely not using binding redirects in your .NET Framework project. In order to use .NET Standard assets in .NET Framework projects, binding redirects are almost always a requirement, and that's the case here. If you enable auto binding redirects in your .NET Framework project, it will notice the version mismatch between your netstandard2.0 lib which uses 6.0.0.0 of ConfigurationManager, and the NuGet package asset you get which is 6.0.0.1, and therefore it will suggest a binding redirect (which if you have auto binding redirects enabled it will just apply it directly to your app config file) for ConfigurationManager from version 0.0.0.0-6.0.0.1 to use version 6.0.0.1.

cc: @ericstj

@joperezr
Copy link
Member

joperezr commented Nov 4, 2022

Reproduction Steps
Create library project that targets netstandard2.0 and references System.Configuration.ConfigurationManager 6.0.1 and run .NET Framework app that uses that library.

FWIW, I just ran your repro steps locally on a .NET Framework console project (which has AutoBindingRedirects on by default) and the app runs just fine as expected. And my App.config in the output folder shows the redirect as I expected:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Configuration.ConfigurationManager" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
      </dependentAssembly>
    </assemblyBinding>
    ....

@Alex-Sob
Copy link
Author

Alex-Sob commented Nov 5, 2022

Thanks, I see, but still I think this is not right. Binding redirects are required only if there are multiple versions of the package, but otherwise we expect it to "just work". We had to investigate why our builds started failing in our repos after we simply upgraded the package version, and we had to waste time to find the cause and fix it by using v6.0.0 instead. So it's like a breaking change. I think it's better to have versions aligned anyway.

@ericstj
Copy link
Member

ericstj commented Nov 7, 2022

We always increment .NETFramework assemblies in servicing since desktop follows the rules of "GAC wins". We never want an un-serviced version installed in the GAC to win over a serviced version in the application.

In this case, the assembly is also part of the WindowsDesktop shared framework in .NET 6. Since assemblies that are part of the shared framework are serviced in-place via central servicing with no action from the app developer we do not change their assembly version in servicing. As such the .NET 6 assembly and all assemblies compatible with it do not change their assembly versions in servicing.

I think it's better to have versions aligned anyway.

In this case, aligning the versions would either mean that .NETFramework customers cannot guarantee a serviced assembly (if we didn't increment) or .NET Core customers would see a breaking change in an in-place update (if we did increment everywhere).

We opt for the change that doesn't break either of these cases, while relying on customers to use bindingRedirects - which we view as a necessity, regardless, when consuming NuGet packages on .NETFramework.

@joperezr
Copy link
Member

joperezr commented Nov 9, 2022

Closing this as the main question has been answered now. @Alex-Sob feel free to reopen if you have any follow up questions/discussion.

@joperezr joperezr closed this as completed Nov 9, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 9, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants