Skip to content

Using latest .NET Core 3.0 packages with Azure Functions v2 (like System.Text.Encodings.Web) causes "Method not found" issue due to assembly version mismatch #5031

Closed
@ahsonkhan

Description

@ahsonkhan

Is your question related to a specific version? If so, please specify:

Azure Functions v2

What language does your question apply to? (e.g. C#, JavaScript, Java, All)

C#

Question

From https://github.com/dotnet/corefx/issues/41534 (System.Text.Json: Method not found System.Text.Encodings.Web.TextEncoder.FindFirstCharacterToEncodeUtf8)

Works perfectly well in every project except Azure Functions (v2).
Simply HTTP trigger an Azure Function and try and serialize (or deserialize) an object.

cc @electricessence, @fabiocav

Is there a workaround to this dependency version pinning issue?

This issue looks similar to #4906.

Here's a repro with a similar error:

System.Private.CoreLib: Exception while executing function: Function1. TestDependency: Method not found: 'System.Text.Encodings.Web.JavaScriptEncoder System.Text.Encodings.Web.JavaScriptEncoder.get_UnsafeRelaxedJsonEscaping()'.
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <AzureFunctionsVersion>v2</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.29" />
    <PackageReference Include="System.Text.Json" Version="4.6.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>
public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string name = req.Query["name"];

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);

        var output = new MemoryStream();
        using (var writer = new Utf8JsonWriter(output, 
            new JsonWriterOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }))
        {
            writer.WriteString(Encoding.UTF8.GetBytes("name"), "Bob1");
            writer.Flush();
        }

        name = System.Text.Json.JsonSerializer.Serialize(Encoding.UTF8.GetString(output.ToArray()));

        return name != null
            ? (ActionResult)new OkObjectResult($"Hello, {name}")
            : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
    }
}
Http Functions:

        Function1: [GET,POST] http://localhost:7071/api/Function1

[10/7/2019 3:09:01 AM] Host lock lease acquired by instance ID '000000000000000000000000B068BFBB'.
[10/7/2019 3:09:07 AM] Executing HTTP request: {
[10/7/2019 3:09:07 AM]   "requestId": "a37a95c1-868d-484d-82d9-f9cc6e34ba3b",
[10/7/2019 3:09:07 AM]   "method": "GET",
[10/7/2019 3:09:07 AM]   "uri": "/api/Function1"
[10/7/2019 3:09:07 AM] }
[10/7/2019 3:09:07 AM] Executing 'Function1' (Reason='This function was programmatically called via the host APIs.', Id=c9432a44-ea43-4ad9-b45a-7b642c43f07c)
[10/7/2019 3:09:08 AM] Executed 'Function1' (Failed, Id=c9432a44-ea43-4ad9-b45a-7b642c43f07c)
[10/7/2019 3:09:08 AM] System.Private.CoreLib: Exception while executing function: Function1. TestDependency: Method not found: 'System.Text.Encodings.Web.JavaScriptEncoder System.Text.Encodings.Web.JavaScriptEncoder.get_UnsafeRelaxedJsonEscaping()'.
[10/7/2019 3:09:09 AM] Executed HTTP request: {
[10/7/2019 3:09:09 AM]   "requestId": "a37a95c1-868d-484d-82d9-f9cc6e34ba3b",
[10/7/2019 3:09:09 AM]   "method": "GET",
[10/7/2019 3:09:09 AM]   "uri": "/api/Function1",
[10/7/2019 3:09:09 AM]   "identities": [
[10/7/2019 3:09:09 AM]     {
[10/7/2019 3:09:09 AM]       "type": "WebJobsAuthLevel",
[10/7/2019 3:09:09 AM]       "level": "Admin"
[10/7/2019 3:09:09 AM]     }
[10/7/2019 3:09:09 AM]   ],
[10/7/2019 3:09:09 AM]   "status": 500,
[10/7/2019 3:09:09 AM]   "duration": 2444
[10/7/2019 3:09:09 AM] }

Looks like the .NET Core 2.2 dependencies are overriding the newer ones that the user code might bring in/rely on:
https://github.com/Azure/azure-functions-host/blob/a63aeed826c4a1ee7c4e8c676bf7557c88a86ba1/src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj#L53-L66

For example: Microsoft.AspNetCore.App version 2.2.7 brings in the version 4.0.3.0 of the assembly where-as the version that S.T.Json depends on is 4.0.4.0 (this is the version that ships in-box with .NET Core 3.0 and is available as part of the latest 4.6.0 NuGet package).

The function output directory has the right dlls:
image

However, Azure Functions is loading the older dll first (that comes built-in with the azure functions cli):
image

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions