UPDATE 2021/11/09: Since the release of .NET 6 yesterday, there is reportedly day 0 support for .NET 6 across App Services and Azure Functions. Unless you have an absolute requirement to use .NET 5, the solution to using the latest and greatest .NET in Azure is .NET 6! I’ve left the rest of the blog post as it was just in case it helps someone, but I predict that it will become something of a relic now that it’s targeting an older version.
I’ve spent the last couple of evenings trying to get a set of Azure Functions migrated from .NET Core 3.1 to .NET 5 so that I can play around with some of the nice new syntax options, nullable contexts and the like. Since .NET 5 has officially been released, it would be justifiable to believe that it would be well supported across the core Microsoft product catalogue, such as in… say… Azure Functions?
Ha! You’re a funny one.
This blog post was originally going to be a tutorial on how to migrate existing Azure Functions over to use .NET 5 with an early preview of the Azure Functions .NET 5 worker. I was hoping that it was going to be a simple case of including a few extra NuGet packages, updating some configuration files and publishing the normal way but I was clearly suffering from an extra strength case of hubris because it has been a painful experience and I still haven’t quite figured out how to actually publish it to Azure (which you might have guessed is quite an important part of the process). There’s even a repository and associated README which has an example project with steps to publish, but I’ve not managed to get that working either as of yet.
I’ve cleaned up the original content I wrote for the blog post and included it verbatim below because I worked hard on it and hopefully it’ll save someone else from going through the same gruelling experience I did.
If you’re interested in upgrading to .NET 5, wait until Azure Functions support it properly. What I managed to get working below stretches the definition of “working” to it’s limit; it broke easily, threw confusing and unclear errors and generally didn’t want to work properly, which is the complete opposite of my previous experience in writing Azure Functions using .NET Core 3.1. It’s pretty much the definition of bleeding edge technology. Here be dragons!
Original Blog Post
I’ve been working on Azure Functions a lot lately and wanted to try out the new features in C# 9 and .NET 5. Unfortunately the process is not at all simple; when I switched my current project over from .NET Core 3.1 to .NET 5 (changing the TargetFramework
value in the .csproj file from netcoreapp3.1
to net5.0
) I hit this pretty scary and terribly unclear error:
Azure Functions Core Tools
Core Tools Version: 3.0.3160 Commit hash: 00aa7f43cc5c5f15241b5e6e5363256f19ceb990
Function Runtime Version: 3.0.14916.0
[2020-12-22T18:37:23.428Z] A host error has occurred during startup operation '551c9e5b-fa5a-441c-bf1a-8662c40c0276'.
[2020-12-22T18:37:23.430Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Value cannot be null. (Parameter 'provider')
Press any to continue....[2020-12-22T18:37:24.844Z] A host error has occurred during startup operation 'ad94cccb-3e68-4222-9c5c-76d382da3129'.
[2020-12-22T18:37:24.845Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
[2020-12-22T18:37:27.242Z] A host error has occurred during startup operation '2653672e-dc9f-4391-b904-98fb25aac422'.
[2020-12-22T18:37:27.243Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
[2020-12-22T18:37:31.645Z] A host error has occurred during startup operation '5943fcd4-c19a-4d0f-a501-bd005f76725f'.
[2020-12-22T18:37:31.646Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
[2020-12-22T18:37:40.060Z] A host error has occurred during startup operation 'c2909c7b-ccf8-4660-a44a-4de5b7f08bed'.
[2020-12-22T18:37:40.061Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
[2020-12-22T18:37:56.449Z] A host error has occurred during startup operation 'c0a5004b-4eed-4a1c-aaf8-32d609609db9'.
[2020-12-22T18:37:56.450Z] System.Private.CoreLib: Could not load type 'System.Diagnostics.DebuggerStepThroughAttribute' from assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Nice.
At the time that I ran into this, I had been working on other changes to my project for a few hours as well so it took me a while to even realise that the move to .NET 5 might have been the cause. After creating a new default Functions app and switching it over in the same way the above error appeared again.
At the time of writing, the support for .NET 5 in Azure Functions is lacklustre at best. Officially, .NET 5 is only supported with an early preview of the Azure Functions .NET 5 worker, meaning that the current process isn’t exactly streamlined. After a lot of effort and testing, I’ve managed to come up with the following steps which should take a .NET Core 3.1 Functions App to .NET 5 <EDIT>This will allow you to run Azure Functions locally using .NET 5, but publishing is still a bit broken from my tests so far</EDIT>.
Steps
<EDIT> If you’ve skipped the start of this blog post, here’s a TL;DR: .NET 5 is, at time of writing, barely supported in Azure Functions. The below won’t get you all the way to a working .NET 5 Azure Function, but it’s here for anyone who wants a head start on trying to get it working themselves</EDIT>
- Ensure that the
PropertyGroup
tag in your .csproj file looks as follows:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>preview</LangVersion>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
</PropertyGroup>
- Add/update the following package references in your .csproj file to
ItemGroup
and check that the versions are correct (note thatMicrosoft.Azure.Functions.Worker.Sdk
andMicrosoft.Azure.Functions.Worker
are both using preview versions)
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.3" />
<PackageReference Include="Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.0-preview1" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.0.0-preview1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
- Add a new file (
Program.cs
) with the following contents:
using Microsoft.Azure.Functions.Worker.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System.Diagnostics;
using System.Threading.Tasks;
//Change to whatever namespace you're using elsewhere
namespace Net5AzureFunctions
{
class Program
{
static async Task Main(string[] args)
{
#if DEBUG
Debugger.Launch();
#endif
var host = new HostBuilder()
.ConfigureAppConfiguration(c => {
c.AddCommandLine(args);
})
.ConfigureFunctionsWorker((c, b) =>
{
b.UseFunctionExecutionMiddleware();
})
.Build();
await host.RunAsync();
}
}
}
- Update
local.settings.json
so thatFUNCTIONS_WORKER_RUNTIME
is set todotnet-isolated
; the whole file will probably look something like this:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
- Change the interface of any Azure Function definitions to use
HttpRequestData
and returnHttpResponseData
(an example of a Function that uses a HTTP trigger and acceptsHttpRequestData
and returnsHttpResponseData
is available in the GitHub Worker Preview repository)
If you want to run it locally from the command line use func host start --verbose
when in the project directory.
If you want to be able to run it directly from Visual Studio, modify the Debug configuration as follows:
- Set “Launch” to “Executable”
- Set “Executable” to “
func
“ - Set “Application arguments” to “
host start --verbose
“
Ensure that you only run it using “Run without debugging” (CTRL
+ F5
); running it with debugging will connect it to func
rather than dotnet
and will make it so that when Debugger.Launch();
is executed your current Visual Studio instance will not be in the list of available debuggers (since it’s busy).
Also, when you stop executing the project make sure to find the open/running command prompt and cancel the current run of func
with CTRL
+ C
otherwise it will continue running even after stopping the debug session in Visual Studio (which will make the next launch fail).
Deploying the Azure Function to Azure
As noted earlier in this blog post, I haven’t actually managed to get this part working yet. The instructions are available on the dotnet worker preview GitHub repo, but every time I’ve tried to follow those instructions I hit an error in Azure which means that the Function doesn’t launch properly and can’t be called successfully (even though it is deployed). Hopefully I’ll get some time to look at this in the next couple of weeks to see if I can progress it further, but until then I’d love to hear from anyone who has successfully gotten this working!
hi matthew, Thank you for this post.
I also migrated an azure function app from .NET Core 3.1 to .net5, and the functions also didn’t run after migrating.
In my case i also had to change the targetframework in the ZIP deploy.pubxml file (\Properties\PublishProfiles\..ZIP Deploy.pubxml).
net5.0
now the functions run with .net5
LikeLike