Reputation: 16831
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
Reputation: 16831
So the root cause of my problem was twofold:
My Class Library project was referencing the Microsoft.AspNetCore.Http
nuget package. This package is not compatible with .NET Core 3.0 and above.
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:
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" />
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
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