urig
urig

Reputation: 16831

Why does my Azure Functions project not recognize classes from Microsoft.AspNetCore.Http assembly?

I have an Azure Functions project targeting netcoreapp3.1. The project references another Class Library project (also targeting netcoreapp3.1) that uses the FormFile class from the Microsoft.AspNetCore.Http assembly.

The Class Library project compiles and tests run through the code successfully but when I run the Azure Functions project I get the following exception:

System.TypeLoadException: Could not load type 'Microsoft.AspNetCore.Http.Internal.FormFile' from assembly 'Microsoft.AspNetCore.Http, Version=3.1.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

My question is why is the azure functions project unable to load the class and how can I fix it?


Here is the project file for the Azure Functions project:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
    <AssemblyName>AzureFunctionsProject</AssemblyName>
    <RootNamespace>AzureFunctionsProject</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.SendGrid" Version="3.0.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="3.0.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="3.0.1" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\ClassLibraryProject.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

And the project file for the Class Library: ClassLibraryProject

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AssemblyName>ClassLibraryProject</AssemblyName>
    <RootNamespace>ClassLibraryProject</RootNamespace>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <None Include="..\.editorconfig" Link=".editorconfig" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Azure.Storage.Blobs" Version="12.4.1" />
    <PackageReference Include="Dapper" Version="2.0.35" />
    <PackageReference Include="Dapper.Contrib" Version="2.0.35" />
    <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
    <PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.3" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="1.0.19269.1" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
  </ItemGroup>
</Project>

Running dotnet --list-runtimes outputs:

Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Upvotes: 1

Views: 1201

Answers (2)

urig
urig

Reputation: 16831

So the root cause of my problem was twofold:

  1. My Class Library project was referencing the Microsoft.AspNetCore.Http nuget package. This package is not compatible with .NET Core 3.0 and above.

  2. My code was using the class Microsoft.AspNetCore.Http.Internal.FormFile which is not available in .NET Core 3.0 and above. (It moved to Microsoft.AspNetCore.Http.FormFile)

ASP.NET Core 3.0 introduced the concept of the shared framework. This is implemented by the Microsoft.AspNetCore.App metapackage which made a large number of Microsoft.AspNetCore.* nuget packages redundant. (But not all of them)

To fix the problem:

  1. I removed this nuget package reference from the Class Library's project file:

    <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
    

    and replaced it with this framework reference:

    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    
  2. In files where I was using the FormFile class, I change this using statement:

    using Microsoft.AspNetCore.Http.Internal;
    

    to this using statement:

    using Microsoft.AspNetCore.Http;
    

Upvotes: 1

Mehmet Taha Meral
Mehmet Taha Meral

Reputation: 3843

If may I ask why are you using FormFile on Azure Functions?

What I would suggest to you is basically use Azure Functions with Blob Trigger - Not HttpTrigger. And you get the file as Stream on Blob Trigger.

If you are writing an API (or you especially need HttpTrigger for some reason), you can get the file over HttpRequestMessage with HttpTrigger. You can create MultipartMemoryStreamProvider and read as multipart (like enctype = multipart/form-data in HTML forms) and read as byte array or whatever you want to process.

Please find the example code block below:

[FunctionName(nameof(UploadFile))]
public static async Task UploadFile([HttpTrigger(Constants.AuthorizationLevel.UploadFile, 
Constants.HttpVerbs.UploadFile, 
Route = Constants.Routes.UploadFile)]HttpRequestMessage req, TraceWriter log)
{
    var streamProvider = new MultipartMemoryStreamProvider();
    await req.Content.ReadAsMultipartAsync(streamProvider);
    var firstFile = streamProvider.Contents.First();
    var fileInfo = firstFile.Headers.ContentDisposition;
    var fileData = await firstFile.ReadAsByteArrayAsync();

    // e.g for image 
    var img = new Image()
    {
        FileName = fileInfo.FileName,
        Size = fileData.LongLength,
        Status = ImageStatus.Processing
    };
};

Hope it helps 🤞🏼

Upvotes: 0

Related Questions