Migrate Azure Function from NET 8 in-process to NET 8 isolated
The migration from NET 8 in-process to NET 8 isolated is not simple and straightforward as migrating from NET 6 in-process to NET 8 in-process. Below I summarize the steps I normally follow with some additional notes and piece of code. Official Microsoft documentation here.
Main steps on the project
Considering a Function project already on NET 8 in-process
- project file:
- under
<PropertyGroup>
add<OutputType>Exe</OutputType>
- remove packages:
Microsoft.NET.Sdk.Functions
Microsoft.Azure.WebJobs.*
Microsoft.Azure.Functions.Extensions
- add the following packages (AppInsight and others are optionals):
<ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.5" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.2" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.2" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" /> <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" /> </ItemGroup>
- check if nuget packages new verioss are available and update them.
- add
<ItemGroup><Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/></ItemGroup>
- add other required packages considering the triggers and binding used by the app (Timer, Queue bindings, etc)
- under
- add Program.cs with required HostBulider
- remove FunctionsStartup code, tipicaly in
Startup.cs
and move code into program.cs / main (e.g.[assembly: FunctionsStartup(typeof(MyProject.Startup))]
) - functions signature:
FunctionName
–>Function
attribute- remove the ILogger from the function signature, declare a constructor like
public MyFunction(ILogger<MyFunction> logger) { _logger = logger;}
And use_logger
in the function body. Use non static methods. - remove unused
using
, likeusing Microsoft.Azure.WebJobs;
- add
using Microsoft.Azure.Functions.Worker;
- review binding and triggers
- local.settings.json:
- add
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
- remove
"FUNCTIONS_INPROC_NET8_ENABLED": "1"
- add
Strange error
You might find yourself stuck with errors like the one below. Sometime this error cover other compile errors. In such a case, check the compile errors in the Output window / Build of Visual Studio. Then, solve all the other compile errors and this will disappear. Some restart of VS 2022 are also usefull. Sometimes an explicit delete of bin
and obj
folders can help.
MSB3202 The project file "C:\.....\FunctApp\obj\Debug\net8.0\WorkerExtensions\WorkerExtensions.csproj" was not found. FunctApp
File: C:\Users\.....\.nuget\packages\microsoft.azure.functions.worker.sdk\2.0.4\build\Microsoft.Azure.Functions.Worker.Sdk.targets
UPDATE: solved in Microsoft.Azure.Functions.Worker.Sdk version 2.0.5
</small>
Application Insights configuration
[TODO: add details…]
See example below.
Program.cs example
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
// ...
// ...
public static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
})
.ConfigureLogging(logging =>
{
// By default, application insights logger starts with this filter rule (level=Warning);
// {ProviderName: 'Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider', CategoryName: '', LogLevel: 'Warning', Filter: ''}
logging.Services.Configure<LoggerFilterOptions>(options =>
{
LoggerFilterRule? defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName == typeof(Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider).FullName);
if (defaultRule is not null)
{
options.Rules.Remove(defaultRule);
}
});
// Note: adding filter is easy. Removing requires more code.
// logging.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(null, LogLevel.Debug);
})
.Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("*****************************************");
logger.LogInformation("Starting Function APP...");
host.Run();
}
Main steps for deploying to Azure
Considering a function app already running as NET 8 in-process
- stop function app
- set
FUNCTIONS_WORKER_RUNTIME = dotnet-isolated
- remove
FUNCTIONS_INPROC_NET8_ENABLED = 1
- deploy from Visual Studio. Before deploying, it will update the .NET Version from
NET 8 in-process
toNET 8 isolated
- start the function app
Misc
Logging on Application Insights : (
What a mess!
https://github.com/Azure/azure-functions-dotnet-worker/issues/2059