System.IO.FileNotFoundException thrown when using System.Text.Json in mixed .Net version solution. Assembly versions do not match.
Description
We have a fairly large code base which consist of different .Net version projects. Mostly .Net6.0 and .NetStandard2.0 but a few .Net Framework 4.7.2 projects as well. We are migrating all of these to .Net6.0 but it will still take a lot of time before everything is done.
The issue we are facing is with System.Text.Json. We have installed the 6.0.5 nuget package to the projects that require it but since couple of them are .Net Framework projects, it seems that they get a different version of the System.Text.Json assembly. For other project types the assembly version is 6.0.0.0 but for the legacy framework it is 6.0.0.5. This causes runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified." when the framework project is referenced by a .Net6.0 project (yes, I know it's not ideal but at the time being a necessary evil).
Reproduction Steps
Create a .Net6.0 and a .Net4.7.2 projects. Add a System.Text.Json reference to the 4.7.2 project and reference that project from the .Net6.0 project. Run the .Net6.0 and it'll throw an System.IO.FileNotFoundException
Here is a sample solution for this: JsonReferenceIssue.zip
Expected behavior
I would expect the NuGet for System.Text.Json 6.0.5 to have the same assembly version for different .Net versions.
Actual behavior
Runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified."
Regression?
No response
Known Workarounds
If I downgrade the projects to use the NuGet 6.0.0 this works as expected.
In the sample solution I can also workaround the issue by adding the following snippet to the Program.cs but I don't feel comfortable of trying to do this in our production code.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static System.Reflection.Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
if (args.Name == "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")
{
return typeof(System.Text.Json.JsonSerializer).Assembly;
}
return null;
}
Configuration
Partial output of dotnet --info:
.NET SDK (reflecting any global.json):
Version: 6.0.301
Commit: 43f9b18481
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.301\
Host (useful for support):
Version: 6.0.6
Commit: 7cca709db2
Other information
I'm not sure if the different System.Text.Json assembly version numbers between the .Net Framework and .Net Core versions is deliberate. If yes, I would like to know how to circumvent this issue.
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.
Issue Details
Description
We have a fairly large code base which consist of different .Net version projects. Mostly .Net6.0 and .NetStandard2.0 but a few .Net Framework 4.7.2 projects as well. We are migrating all of these to .Net6.0 but it will still take a lot of time before everything is done.
The issue we are facing is with System.Text.Json. We have installed the 6.0.5 nuget package to the projects that require it but since couple of them are .Net Framework projects, it seems that they get a different version of the System.Text.Json assembly. For other project types the assembly version is 6.0.0.0 but for the legacy framework it is 6.0.0.5. This causes runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified." when the framework project is referenced by a .Net6.0 project (yes, I know it's not ideal but at the time being a necessary evil).
Reproduction Steps
Create a .Net6.0 and a .Net4.7.2 projects. Add a System.Text.Json reference to the 4.7.2 project and reference that project from the .Net6.0 project. Run the .Net6.0 and it'll throw an System.IO.FileNotFoundException
Here is a sample solution for this: JsonReferenceIssue.zip
Expected behavior
I would expect the NuGet for System.Text.Json 6.0.5 to have the same assembly version for different .Net versions.
Actual behavior
Runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified."
Regression?
No response
Known Workarounds
If I downgrade the projects to use the NuGet 6.0.0 this works as expected.
In the sample solution I can also workaround the issue by adding the following snippet to the Program.cs but I don't feel comfortable of trying to do this in our production code.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static System.Reflection.Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
if (args.Name == "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")
{
return typeof(System.Text.Json.JsonSerializer).Assembly;
}
return null;
}
Configuration
Partial output of dotnet --info:
.NET SDK (reflecting any global.json):
Version: 6.0.301
Commit: 43f9b18481
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.301\
Host (useful for support):
Version: 6.0.6
Commit: 7cca709db2
Other information
I'm not sure if the different System.Text.Json assembly version numbers between the .Net Framework and .Net Core versions is deliberate. If yes, I would like to know how to circumvent this issue.
| Author: | skelendal |
|---|---|
| Assignees: | - |
| Labels: |
|
| Milestone: | - |
We are facing the same issue, thanks for providing an workaround @skelendal
There is a warning message this project shows up:
warning MSB3277: Found conflicts between different versions of "System.Text.Json" that could not be resolved.
warning MSB3277: There was a conflict between "System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" and "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51".
warning MSB3277: "System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was chosen because it was primary and "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was not.
warning MSB3277: References which depend on "System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" [C:\Users\xyz\.nuget\packages\microsoft.netcore.app.ref\6.0.7\ref\net6.0\System.Text.Json.dll].
warning MSB3277: C:\Users\xyz\.nuget\packages\microsoft.netcore.app.ref\6.0.7\ref\net6.0\System.Text.Json.dll
warning MSB3277: Project file item includes which caused reference "C:\Users\xyz\.nuget\packages\microsoft.netcore.app.ref\6.0.7\ref\net6.0\System.Text.Json.dll".
warning MSB3277: C:\Users\xyz\.nuget\packages\microsoft.netcore.app.ref\6.0.7\ref/net6.0/System.Text.Json.dll
warning MSB3277: References which depend on "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" [].
warning MSB3277: C:\Users\xyz\Downloads\JsonReferenceIssue\DotNetLib\bin\Debug\net6.0\DotNetLib.dll
warning MSB3277: Project file item includes which caused reference "C:\Users\xyz\Downloads\JsonReferenceIssue\DotNetLib\bin\Debug\net6.0\DotNetLib.dll".
warning MSB3277: C:\Users\xyz\Downloads\JsonReferenceIssue\DotNetLib\bin\Debug\net6.0\DotNetLib.dll
warning MSB3277: C:\Users\xyz\Downloads\JsonReferenceIssue\LegacyLib\bin\Debug\net472\LegacyLib.dll
warning MSB3277: Project file item includes which caused reference "C:\Users\xyz\Downloads\JsonReferenceIssue\LegacyLib\bin\Debug\net472\LegacyLib.dll".
warning MSB3277: C:\Users\xyz\Downloads\JsonReferenceIssue\LegacyLib\bin\Debug\net472\LegacyLib.dll
but other than that everything looks correct:
- JsonReferenceIssue [net6.0] references S.T.Json 6.0.0, DotNetLib, LegacyLib
- DotNetLib [net6.0] references S.T.Json 6.0.0
- LegacyLib [net472] references S.T.Json 6.0.5 (per @ViktorHofer this is correct according to https://github.com/dotnet/runtime/issues/46178)
there isn't any good workaround like binding redirects for that as well (I've tried adding .exe.config and App.config with different knobs and none of that seem to have any effect).
Project is attached in the main issue.
cc: @dotnet/area-infrastructure-libraries @joperezr @ericstj @ViktorHofer
Tagging subscribers to this area: @dotnet/runtime-infrastructure See info in area-owners.md if you want to be subscribed.
Issue Details
Description
We have a fairly large code base which consist of different .Net version projects. Mostly .Net6.0 and .NetStandard2.0 but a few .Net Framework 4.7.2 projects as well. We are migrating all of these to .Net6.0 but it will still take a lot of time before everything is done.
The issue we are facing is with System.Text.Json. We have installed the 6.0.5 nuget package to the projects that require it but since couple of them are .Net Framework projects, it seems that they get a different version of the System.Text.Json assembly. For other project types the assembly version is 6.0.0.0 but for the legacy framework it is 6.0.0.5. This causes runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified." when the framework project is referenced by a .Net6.0 project (yes, I know it's not ideal but at the time being a necessary evil).
Reproduction Steps
Create a .Net6.0 and a .Net4.7.2 projects. Add a System.Text.Json reference to the 4.7.2 project and reference that project from the .Net6.0 project. Run the .Net6.0 and it'll throw an System.IO.FileNotFoundException
Here is a sample solution for this: JsonReferenceIssue.zip
Expected behavior
I would expect the NuGet for System.Text.Json 6.0.5 to have the same assembly version for different .Net versions.
Actual behavior
Runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified."
Regression?
No response
Known Workarounds
If I downgrade the projects to use the NuGet 6.0.0 this works as expected.
In the sample solution I can also workaround the issue by adding the following snippet to the Program.cs but I don't feel comfortable of trying to do this in our production code.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static System.Reflection.Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
if (args.Name == "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")
{
return typeof(System.Text.Json.JsonSerializer).Assembly;
}
return null;
}
Configuration
Partial output of dotnet --info:
.NET SDK (reflecting any global.json):
Version: 6.0.301
Commit: 43f9b18481
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.301\
Host (useful for support):
Version: 6.0.6
Commit: 7cca709db2
Other information
I'm not sure if the different System.Text.Json assembly version numbers between the .Net Framework and .Net Core versions is deliberate. If yes, I would like to know how to circumvent this issue.
| Author: | skelendal |
|---|---|
| Assignees: | - |
| Labels: |
|
| Milestone: | 8.0.0 |
Tagging subscribers to this area: @dotnet/area-infrastructure-libraries See info in area-owners.md if you want to be subscribed.
Issue Details
Description
We have a fairly large code base which consist of different .Net version projects. Mostly .Net6.0 and .NetStandard2.0 but a few .Net Framework 4.7.2 projects as well. We are migrating all of these to .Net6.0 but it will still take a lot of time before everything is done.
The issue we are facing is with System.Text.Json. We have installed the 6.0.5 nuget package to the projects that require it but since couple of them are .Net Framework projects, it seems that they get a different version of the System.Text.Json assembly. For other project types the assembly version is 6.0.0.0 but for the legacy framework it is 6.0.0.5. This causes runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified." when the framework project is referenced by a .Net6.0 project (yes, I know it's not ideal but at the time being a necessary evil).
Reproduction Steps
Create a .Net6.0 and a .Net4.7.2 projects. Add a System.Text.Json reference to the 4.7.2 project and reference that project from the .Net6.0 project. Run the .Net6.0 and it'll throw an System.IO.FileNotFoundException
Here is a sample solution for this: JsonReferenceIssue.zip
Expected behavior
I would expect the NuGet for System.Text.Json 6.0.5 to have the same assembly version for different .Net versions.
Actual behavior
Runtime error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified."
Regression?
No response
Known Workarounds
If I downgrade the projects to use the NuGet 6.0.0 this works as expected.
In the sample solution I can also workaround the issue by adding the following snippet to the Program.cs but I don't feel comfortable of trying to do this in our production code.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static System.Reflection.Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
if (args.Name == "System.Text.Json, Version=6.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")
{
return typeof(System.Text.Json.JsonSerializer).Assembly;
}
return null;
}
Configuration
Partial output of dotnet --info:
.NET SDK (reflecting any global.json):
Version: 6.0.301
Commit: 43f9b18481
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.301\
Host (useful for support):
Version: 6.0.6
Commit: 7cca709db2
Other information
I'm not sure if the different System.Text.Json assembly version numbers between the .Net Framework and .Net Core versions is deliberate. If yes, I would like to know how to circumvent this issue.
| Author: | skelendal |
|---|---|
| Assignees: | - |
| Labels: |
|
| Milestone: | 8.0.0 |
The behavior is expected. While we try to make .NETFramework library reuse in .NET Core / .NET5+ a possibility, it's not a guarantee. In this case we have conflicting requirements, and we prioritize the correct behavior on the individual platforms over the reuse of the .NETFramework library in the .NETCore/.NET5+ application.
Those requirements, as were mentioned in the linked issue are:
- Guarantee that .NETFramework assemblies always version to ensure that an un-serviced assembly will never win over a serviced assembly.
- Guarantee that a .NETCore / .NET5 assembly that also ships in the shared framework does not change in servicing (since updates can happen in place).
Note that you'll see the following type of warning when you attempt to add a reference to a .NETFramework library from a .NETCore/.NET5+ application. These warnings are here specifically to tell you that you're in unsupported territory and will face problems like the one reported ehre.
C:\scratch\netfxreuse\app>dotnet add reference ..\lib\lib.csproj
Project `C:\scratch\netfxreuse\lib\lib.csproj` cannot be added due to incompatible targeted frameworks between the two projects. Review the project you are trying to add and verify that is compatible with the following targets:
- net6.0
Now suppose I ignore this and manually add the reference and build:
C:\Program Files\dotnet\sdk\7.0.100-rc.1.22431.11\Microsoft.Common.CurrentVersion.targets(1830,5): warning NU1702: Proj
ectReference 'C:\scratch\netfxreuse\lib\lib.csproj' was resolved using '.NETFramework,Version=v4.8' instead of the proj
ect target framework '.NETCoreApp,Version=v6.0'. This project may not be fully compatible with your project. [C:\scratc
h\netfxreuse\app\app.csproj]
I see you disabled this warning in your example.
<NoWarn>1701;1702;NU1701;NU1702</NoWarn>
If you'd like to reuse libraries in .NETFramework and .NETCore apps you can have those libraries target netstandard2.0 -- this is the recommended path for library reuse and will work without warnings.
If you wanted a hack, that would be safe to use in a .NETFramework library only you could force that library to use the netstandard2.0 assembly from System.Text.Json. This would allow the library to compile as if it were a netstandard2.0 library using the version which is compatibile with .NETCore. This is only safe to do for a library, since it violates the requirement 1 above, and it also uses a different implementation than the one that's preferred on .NETFramework. When doing this you would need to make sure your .NETFramework applications, which actually execute code, get the correct assembly and a bindingRedirect - this should be automatic if you're using PackageReference and automtatic bindingRedirects but you should double check.
<!-- Hack -- use the `netstandard2.0` System.Text.Json library when compiling .NETFramework libraries (not applications)
May be included in Directory.Build.targets if you understand what it's doing and why you are using it. -->
<ItemGroup Condition="'$(OutputType)' == 'Library' AND '$(TargetFrameworkIdentifier)' == '.NETFramework' AND '@(PackageReference->AnyHaveMetadataValue('Identity', 'System.Text.Json'))'">
<!-- prevent the default reference for S.T.J to be used-->
<PackageReference Update="System.Text.Json" ExcludeAssets="compile;runtime" GeneratePathProperty="true" />
<!-- reference the `netstandard2.0` library, private=false to ensure it's never copied -->
<Reference Condition="'$(PkgSystem_Text_Json)' != ''" Include="$(PkgSystem_Text_Json)\lib\netstandard2.0\System.Text.Json.dll" Private="false" />
</ItemGroup>
Here's a sample: https://github.com/ericstj/sample-code/tree/netfx-library-reuse.
PS: I believe @AArnott was also faced with this problem and solved it with a runtime AssemblyResolve event that redirects the references down, as your workaround does.
Yes, I hit this too. On .NET Framework we use binding redirects. On .NET 6 I .... use binding redirects too! :) Something like this:
<bindingRedirect oldVersion="4.0.0.0-6.0.0.5" newVersion="6.0.0.0" />
But wait, you say, .NET doesn't have .config files, so binding redirects don't apply, right? Well, true. And ultimately as @ericstj said, this does boil down to a custom assembly resolve event handler. But for purposes of easing migration of .NET Framework apps to .NET, I wrote Nerdbank.NetStandardBridge which includes a class that reads .config files and implements a custom assembly resolver (and creates ALCs as required) to implement nearly all the behaviors of the CLR when it comes to assembly loaders.
And while it certainly isn't great to be running assemblies compiled for .NET Framework on .NET 6, during a migration it may be expedient to do just that, leaving assembly references to the 6.0.0.5 assembly version of something that on .NET 6 is only 6.0.0.0. So you can do the assembly resolve thing directly, or if it's useful to carry your .config file over anyway as well, you may find this library useful, and then you can just encode things like this as a binding redirect.
Here's a sample: https://github.com/ericstj/sample-code/tree/netfx-library-reuse.
@ericstj With ExcludeAssets="all" on the System.Text.Json PackageReference, will the msbuild files under buildTransitive and the analyzer files under analyzers still be picked up? Asking as ExcludeAssets suggests that any asset is excluded which would disable the source generator feature. You might need an additional Analyzer item in your hack.
The analyzers are picked up regardless of values for Exclude (unfortunately) due to https://github.com/dotnet/sdk/issues/1212. We shouldn't however exclude the targets. I'll update the sample to only exclude compile and runtime.
This issue has been marked needs-author-action and may be missing some important information.
This issue has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.
This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.