Azure / azure-iot-sdk-csharp

A C# SDK for connecting devices to Microsoft Azure IoT services
Other
466 stars 493 forks source link

[Bug Report] The last version 1.38 is not compatible with .netcore3.1 #2170

Closed Dolphinsimon closed 3 years ago

Dolphinsimon commented 3 years ago

Description of the issue

We have some azure function apps running in the V3 .NET runtime. After update the Microsoft.Azure.Devices.Client to version 1.38, we got the error: Could not load file or assembly 'Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.

If we trying to install the package directly, the package downgrade error occurred:

Detected package downgrade: Microsoft.Extensions.Logging from 5.0.0 to 3.1.19. Reference the package directly from the project to select a different version. FunctionApp -> Microsoft.Azure.Devices.Client 1.38.0 -> DotNetty.Handlers 0.7.0 -> DotNetty.Common 0.7.0 -> Microsoft.Extensions.Logging (>= 5.0.0) FunctionApp -> Microsoft.Extensions.Logging (>= 3.1.19)

Detected package downgrade: Microsoft.Extensions.Logging from 5.0.0 to 3.1.19. Reference the package directly from the project to select a different version. FunctionApp -> Microsoft.Azure.Devices.Client 1.38.0 -> DotNetty.Codecs.Mqtt 0.7.0 -> DotNetty.Common 0.7.0 -> Microsoft.Extensions.Logging (>= 5.0.0) FunctionApp -> Microsoft.Extensions.Logging (>= 3.1.19)

Seems the Microsoft.Extensions.Logging version 5.0.0 is not compatible with .netcore3.1. We have to downgrade the Microsoft.Azure.Devices.Client to version 1.37.2 to fix this.

jamdavi commented 3 years ago

Hey @Dolphinsimon I created a simple console Application for NetCore 3.1 and added the IoT Package and it compiled fine. I then went back and attempted to add the 3.1.19 version of the logging extensions and was able to get the error.

I then also installed IoT 1.37.2 and the 3.1.19 Logging package, I then updated IoT and got the error.

What I suspect is your FunctionApp has a reference to the old version of the logging extensions. You should upgrade that package to the latest version.

If you look at your NuGet packages you should see something like this.

image

Steps to repro as you see it.

  1. Have a project with NuGet packages IoT 1.37.2 and Logging 3.1.19
  2. Update to 1.38.0
  3. Get the error below
Restoring packages for C:\Users\jamdavi\source\repos\ConsoleNetCore31\ConsoleNetCore31\ConsoleNetCore31.csproj...
NU1605: Detected package downgrade: Microsoft.Extensions.Logging from 5.0.0 to 3.1.19. Reference the package directly from the project to select a different version. 
 ConsoleNetCore31 -> Microsoft.Azure.Devices.Client 1.38.0 -> DotNetty.Codecs.Mqtt 0.7.0 -> DotNetty.Common 0.7.0 -> Microsoft.Extensions.Logging (>= 5.0.0) 
 ConsoleNetCore31 -> Microsoft.Extensions.Logging (>= 3.1.19)
NU1605: Detected package downgrade: Microsoft.Extensions.Logging from 5.0.0 to 3.1.19. Reference the package directly from the project to select a different version. 
 ConsoleNetCore31 -> Microsoft.Azure.Devices.Client 1.38.0 -> DotNetty.Handlers 0.7.0 -> DotNetty.Common 0.7.0 -> Microsoft.Extensions.Logging (>= 5.0.0) 
 ConsoleNetCore31 -> Microsoft.Extensions.Logging (>= 3.1.19)
Package restore failed. Rolling back package changes for 'ConsoleNetCore31'.
Dolphinsimon commented 3 years ago

@jamdavi Thanks for your testing. The build with 1.38.0 in .netcore3.1 is always success. It just cannot start in Azure Function .NET V3 environment. If you create a function with 1.38.0 and publish it to azure, you will see the error. Could not load file or assembly 'Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.

Dolphinsimon commented 3 years ago

I guess it can be run in local machine because we have .net5.0 sdk/runtime installed, the package Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0 can be found in local environment. But the Azure function .NET V3 runtime does not have .net5.0 packages.

jamdavi commented 3 years ago

TL;DR As you might have guessed the easiest way to get around this for the new package is set the FUNCTIONS_EXTENSION_VERSION to ~4

This isn't a problem with the IoT SDK and the version of .NET but instead the specific packages that are loaded and referenced by the FunctionApp.

Microsoft.Extensions.Logging.Abstractions 5.0.0.0 is compatible with Net Core 3.1 because Net Core 3.1 is compatible with Net Standard 2.0. The 5.0.0.0 version isn't indicating it only supports net50. So, as long as you have netcore3.1 installed this should all work. At least it should work in most instances; mind you there is a HUGE asterisk next to this in context of this problem.

There are two things that happen here:

  1. The FunctionApp has it's predefined set of assemblies.
  2. The package/publish does not include all assemblies if they are included in the FunctionApp environment

You can overcome item 1 by following the instructions in issue 298 for the function build by adding the following to the csproj file. But this can cause some problems with assembly references in the FunctionApp as I found out.

https://github.com/Azure/azure-functions-vs-build-sdk/issues/298

 <PropertyGroup>
    <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput> 
  </PropertyGroup>

Since the version of the FunctionApp runtime has it's predefined assemblies it loads, everything is referenced to some specific versions. In this case 3.1.19. That is unless there is another version available in the FunctionApp folder.

In my testing if I overwrote this file it would cause the FunctionApp to fail because there is a difference between the methods available in the 3.1.19 assembly and the 5.0.0.0. It would manifest as a MethodNotFound excpetion when trying to access the QueryString.

In later versions of the FunctionApp package, it of course, attempts to use net50 and other versions of the extensions assembly. If you use the later version the problem goes away.

There is no other workaround that I could suggest that is as clean as it should be. You can try various combinations of include and copy files, but the best suggestions are

  1. Revert to the old package to avoid this assembly conflict
  2. Update the FUNCTIONS_EXTENSION_VERSION to ~4
Dolphinsimon commented 3 years ago

TL;DR As you might have guessed the easiest way to get around this for the new package is set the FUNCTIONS_EXTENSION_VERSION to ~4

This isn't a problem with the IoT SDK and the version of .NET but instead the specific packages that are loaded and referenced by the FunctionApp.

Microsoft.Extensions.Logging.Abstractions 5.0.0.0 is compatible with Net Core 3.1 because Net Core 3.1 is compatible with Net Standard 2.0. The 5.0.0.0 version isn't indicating it only supports net50. So, as long as you have netcore3.1 installed this should all work. At least it should work in most instances; mind you there is a HUGE asterisk next to this in context of this problem.

There are two things that happen here:

  1. The FunctionApp has it's predefined set of assemblies.
  2. The package/publish does not include all assemblies if they are included in the FunctionApp environment

You can overcome item 1 by following the instructions in issue 298 for the function build by adding the following to the csproj file. But this can cause some problems with assembly references in the FunctionApp as I found out.

Azure/azure-functions-vs-build-sdk#298

 <PropertyGroup>
    <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput> 
  </PropertyGroup>

Since the version of the FunctionApp runtime has it's predefined assemblies it loads, everything is referenced to some specific versions. In this case 3.1.19. That is unless there is another version available in the FunctionApp folder.

In my testing if I overwrote this file it would cause the FunctionApp to fail because there is a difference between the methods available in the 3.1.19 assembly and the 5.0.0.0. It would manifest as a MethodNotFound excpetion when trying to access the QueryString.

In later versions of the FunctionApp package, it of course, attempts to use net50 and other versions of the extensions assembly. If you use the later version the problem goes away.

There is no other workaround that I could suggest that is as clean as it should be. You can try various combinations of include and copy files, but the best suggestions are

  1. Revert to the old package to avoid this assembly conflict
  2. Update the FUNCTIONS_EXTENSION_VERSION to ~4

Thanks for that, I will try to set function version to ~4

jamdavi commented 3 years ago

@Dolphinsimon Did you get a chance to try this?

Dolphinsimon commented 3 years ago

@jamdavi We have tried set version ~4, But we got a runtime error. As our Azure Environment is Azure China not the Azure Public Cloud, it might not support ~4 version configuration. Seems we can only stay on version 1.37.2 for now.

jamdavi commented 3 years ago

Thanks @Dolphinsimon. I'm going to close this one for now as there we need to have the later runtime version for this to work on function apps.