Azure Functions in .NET 5
Originally, when .NET 5 was first released in November 2020, there was no general support for Azure Functions. In this piece, I aim to discuss why .NET 5 wasn’t supported for Azure Functions initially and how Microsoft has dealt with these issues. Additionally, I will also be covering whether or not it is worth upgrading your .NET Core 3.1 functions and what the differences between .NET Core 3.1 and .NET 5 Azure Functions are.
As of March 2021, Microsoft announced that Azure Functions are supported running on .NET 5. But why weren’t Azure Functions initially supported?
You were unable to use .NET 5 prior to March 2021, due to tight coupling between the Azure Functions runtime and .NET. This means that Azure functions running in-process are required to run on the same version of .NET as the Functions runtime. To deal with this, Microsoft introduced .NET Isolated Process Functions. This is an out-of-process model which runs a .NET 5 worker process alongside the runtime. It was introduced so that we can run Azure Functions runtime version 3 on .NET 5.
It is worth noting that the future of .NET releases require Azure Functions to run on an isolated process. Additionally, Durable Functions will not be supported on the isolated process until .NET 7 based on the following roadmap.
So…. Is it worth upgrading?
As per the roadmap above, you may wonder whether or not migrating to .NET 5 is worth it, based on long term support (LTS) not being available until .NET 6.
Due to the future of .NET releases requiring Azure Functions to run in an isolated process, it could be worthwhile to do the work now in hope that the migration from .NET 5 to .NET 6 will be much simpler. Additionally, there are many benefits to using an out-of-process function, such as gaining full control of the process, and using existing .NET code for dependency injection and being able to introduce middleware.
In some cases, such as Durable Functions not being available, you may be required to continue to use .NET Core 3.1 and the in-process model.
Differences between .NET Core 3.1 and .NET 5 Azure Functions
You’ll need .NET 5.0 installed and Visual Studio 2019 (version 16.10 or later) with the Azure development workloads also installed to be able to create .NET 5 Azure Functions.
Note: You can use 16.9 but the debugging process is slightly more complicated, using 16.10 means that you can debug using the normal F5 route, ensuring you allow access to the firewall for the .NET Host.
The local.settings.json
file is different, where the FUNCTIONS_WORKER_RUNTIME
has changed from dotnet
to dotnet-isolated
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"AzureWebJobsStorage": "UseDevelopmentStorage=true"
}
The project file has the TargetFramework set to net5.0
and the OutputType as Exe
. This new OutputType is required because a .NET 5 Azure Function is essentially a .NET Console App that targets .NET 5. The AzureFunctionsVersion remains as v3.
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
</PropertyGroup>
The following changes will differ based on the type of trigger you use. The following example will be for a HttpTrigger.
The NuGet Packages required to run a HttpTrigger Azure Function in .NET 5 are the following:
- Microsoft.Azure.Functions.Worker
- Microsoft.Azure.Functions.Worker.Extensions.Http
- Microsoft.Azure.Functions.Worker.Sdk
There are some differences between these code snippets. Firstly, the FunctionName
attribute now becomes Function
. Additionally, you must now use HttpRequestData
and HttpResponseData
. The out-of-process function does not have access to the original HTTP request object, this gets converted to a HttpRequestData
object.
Using ILogger
directly now no longer works and you will receive an ArgumentNullException
. To access the ILogger
instance, you must use the FunctionContext
object passed to your function and call the GetLogger
method.
A Program.cs
file now exists in a .NET 5 Azure Function which forms the entry point of the application. I have also included .ConfigureServices
block, where you will have to move any of your existing dependencies to. You can also set up Middleware here.
References
About the Author
Stephanie is a Senior Software Engineer in the External Product Feeds team at ASOS. When she’s not coding, she enjoys RPM and BodyAttack classes at the gym and spending as much time as possible with her two house rabbits.