azure-functions-host: Incorrect version of Grpc is being used (package version ignored)

I am using the NuGet package Google.Cloud.Firestore which relies on some other packages where type forwarding is used. The forwarded types are not found and result in a MissingMethodException.

The issue occurs when debugging locally in VS Code on macOS. I haven’t deployed this yet.

The same code works in a .NET Core console app.

A lot more details at the original issue: https://github.com/googleapis/google-cloud-dotnet/issues/3101

Investigative information

  • Timestamp: Monday June 3th
  • Function App version: 2.0

Repro steps

See original issue above

Expected behavior

Type forwarding is working and no MissingMethodException

Actual behavior

MissingMethodException when this calls into a forwarded type.

Known workarounds

?

Related information

  • Programming language used: C#
  • Links to source: email me for this (sam@debruyn.dev)
  • Bindings used: QueueTrigger

Csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AzureFunctionsVersion>v2</AzureFunctionsVersion>
    <RootNamespace>myappname</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.4"/>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.24"/>
    <PackageReference Include="PuppeteerSharp" Version="1.17.1"/>
    <PackageReference Include="Google.Cloud.Firestore" Version="1.0.0-beta20"/>
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="google.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 2
  • Comments: 26 (3 by maintainers)

Most upvoted comments

@fabiocav I just had this problem and when @jskeet wrote “func.deps.json” it opened my eyes and I just remembered this issue: https://github.com/Azure/azure-functions-host/issues/4304

So I just added your fix for the WCF ref to my project file and boom, it worked:

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
   <!--https://github.com/Azure/azure-functions-host/issues/3568-->
   <!--<Exec Command="copy $(OutDir)bin\runtimes\win\lib\netstandard2.0\System.Private.ServiceModel.dll $(OutDir)bin\System.Private.ServiceModel.dll" />-->
   <Exec Command="copy $(OutDir)$(ProjectName).deps.json $(OutDir)bin\function.deps.json" />
 </Target>
 <Target Name="PostPublish" BeforeTargets="AfterPublish">
   <!--https://github.com/Azure/azure-functions-host/issues/3568-->
   <!--<Exec Command="copy $(PublishDir)bin\runtimes\win\lib\netstandard2.0\System.Private.ServiceModel.dll $(PublishDir)bin\System.Private.ServiceModel.dll" />-->
   <Exec Command="copy $(PublishDir)$(ProjectName).deps.json $(PublishDir)bin\function.deps.json" />
 </Target>

I fixed it by adding this line into @jslaybaugh BeforeTargets=“CreateZipFile” <Exec Command="copy $(PublishDir)runtimes\win\native\*.* $(PublishDir)bin\" />

@wikes82 me too! But only if it runs through the publish on Azure DevOps. I’ve got a ticket open with them now about that. If I right click and tell it to do a zip deploy from VS (Windows) it works in Azure Functions for me with the following code:

	<Target Name="PostBuildWindows" AfterTargets="PostBuildEvent">
		<!-- https://github.com/Azure/azure-functions-host/issues/3568 -->
		<Exec Command="copy $(OutDir)$(ProjectName).deps.json $(OutDir)bin\function.deps.json" />
	</Target>
	<Target Name="PostPublishWindows" BeforeTargets="CreateZipFile">
		<!-- https://github.com/Azure/azure-functions-host/issues/3568 -->
		<Exec Command="copy $(PublishDir)$(ProjectName).deps.json $(PublishDir)bin\function.deps.json" />
	</Target>

Note the BeforeTargets="CreateZipFile" I’m now using.

Okay, even simpler repro - and an explanation.

First, the project file:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AzureFunctionsVersion>v2</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Grpc.Core" Version="1.21.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.24" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Next, source code:

using Grpc.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;

namespace FunctionApp1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
        {
            CreateChannelCredentials(null);
            return new OkObjectResult("Passed");
        }

        private static ChannelCredentials CreateChannelCredentials(CallCredentials callCredentials) =>
            ChannelCredentials.Create(new SslCredentials(), callCredentials);
    }
}

This fails with the same MissingMethodException when you try to execute CreateChannelCredentials, when the JIT compiler works on that method - because it can’t find the method.

The problem is that it’s not loading Grpc.Core 1.21.0 at all - it’s using 1.18.0 which is in C:\Users\skeet\AppData\Local\AzureFunctionsTools\Releases\2.22.0\cli\

If you update the cli directory to contain the relevant files from Grpc.Core and Grpc.Core.Api, and update func.deps.json accordingly, it all works - including Google.Cloud.Firestore.

So basically, this is a problem for any function needing to use a version of Grpc.Core later than the one embedded in the CLI application.

Note: the same issue occurs using the emulator from Windows and VS2019.