apm-agent-dotnet icon indicating copy to clipboard operation
apm-agent-dotnet copied to clipboard

Update `System.Threading.Tasks.Dataflow` to resolve transistive resolution issues on net462

Open stevejgordon opened this issue 1 year ago • 0 comments

When adding Elastic.Apm.AspNetFullFramework on projects targetting older .NET Framework versions, various oddities may occur with regard to the final packages for libraries such as System.Net.Http. The reasons for this are complex and historical, mostly around the netstandard2.0 work Microsoft did and the addition of OOB packages for these libraries.

For example: In a new default app ASP.NET application targetting .NET Framework 4.7.1, it resolves System.Net.Http from 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.1\System.Net.Http.dll', which carries a version of 4.0.0. After adding Elastic.Apm.AspNetFullFramework, .NET framework may load the DLL from Microsoft.NET.Build.Extensions, which has a newer version number (4.2.0.0).

Specifically, this appears to be triggered by our inclusion of System.Threading.Tasks.Dataflow 4.9.0. Logs don't specifically show changes to any installed dependencies for System.Net.Http, but they may occur thanks to "fixes" in the .NET SDK. We can't control this directly, and it's a legacy of some of the binding issues around .NET Framework and netstandard2.0. One of the most reliable ways to avoid some of the surprising behaviour is to use .NET Framework 4.7.2+, which may not exhibit as many caveats for package resolution and binding for framework dependencies.

See this StackOverflow issues reporting the behaviour and also this issue in the https://github.com/dotnet/runtime/issues/24382 providing additional details about the behaviour. It provides a lot of examples of similar reports and some of the details as to the causes and complexity in dealing with this. This thread is also relevant.

One solution is to consider updating our dependency on System.Threading.Tasks.Dataflow to at least 4.11.1, which appears to avoid some of the Microsoft hacks kicking in and unexpected DLL locations being used. However, this has a knock-on effect for other dependencies such as System.ValueTuple and System.Runtime.InteropServices.RuntimeInformation. I have explored these in this commit. Our concern is that these changes are hard to test for other unexpected side-effects and may negatively affect consuming applications. As a result, we have decided to avoid making this change right now but document the behaviour here so that we can refer back to the details.

This change would also trigger rework to the use of HttpClient.ServerCertificateCustomValidationCallback because the framework version of System.Net.Http in net462 does not include this API which was added in 4.1 contract revisions.

We should revisit this as part of the work to update the payload sending to our new ingest libraries based on Elastic.Transport and a potential 2.0 release since it would allow us to signal that these changes are potentially breaking for some applications targetting older .NET Frameworks.

stevejgordon avatar Jun 09 '23 09:06 stevejgordon