June 19, 2025

Upgrading to .NET 8 Isolated Azure Functions: A Complete Step-by-Step Guide

Introduction

The .NET Isolated Worker Model enables developers to build Azure Functions using a .NET console app project that targets a supported .NET runtime. This model provides greater flexibility, improved performance, and better debugging capabilities compared to the in-process model.

In this guide, we will walk you through upgrading your existing Azure Functions project to .NET 8 using the isolated worker model.


Required Files in a .NET Isolated Project

A .NET-isolated Azure Functions project requires the following essential files:

  • host.json — Configuration file for host settings.
  • local.settings.json — Stores local configurations.
  • .csproj file — Defines the project and dependencies.
  • Program.cs — The entry point for the application.
  • Function code files — Contain your function implementations.

Updating the .csproj File

The first step is to convert the project file and update its dependencies.


Existing .NET 3.x Project (.csproj)


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <None Remove="Functions\host.json" />
    <None Remove="stylecop.json" />
  </ItemGroup>
  <ItemGroup>
    <AdditionalFiles Include="stylecop.json" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Azure.Core" Version="1.13.0" />
    <PackageReference Include="Azure.Storage.Common" Version="12.7.2" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.4" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.25" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.27" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.9" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.4.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.12" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.4" />
    <!-- Your remaining packages -->
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

Updated .NET 8 Project (.csproj)

Make the following changes:

  • Set <TargetFramework> to net8.0.
  • Set <AzureFunctionsVersion> to v4.
  • Add <OutputType>Exe</OutputType>.
  • Replace Microsoft.NET.SDK.Functions With the following packages:


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
    <!-- Your remaining packages -->
  </ItemGroup>
</Project>

Add the following new ItemGroup:


<ItemGroup> 
  <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" /> 
</ItemGroup>

After you make these changes, your updated project should look like this:


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.CosmosDB" Version="4.11.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs" Version="6.6.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>

To make all the above changes automatically, we can make use of the .NET UPGRADE ASSISTANT Extension.


Your isolated worker model application should not reference any packages from Microsoft.Azure.WebJobs.* namespace or Microsoft.Azure.Functions.Extensions.

If you have any remaining references to these, they should be removed.


Updating the host.json File

Your host.json The file plays a critical role in configuring the runtime behavior of your Azure Functions. Below is a sample configuration for an upgraded .NET 8 isolated function:


{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            },
            "enableLiveMetricsFilters": true
        }
    },
    "functionTimeout": "00:05:00", // Set the time according to your needs
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.0.0, 5.0.0)"
    }
}

Note: Please add this functionTimeout based on your function app plan. More details can be found here.

Updating the Program.cs File

The Program.cs file replaces FunctionStartup and serves as the application’s entry point


using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = new HostBuilder();
if (builder != null)
{
    builder.ConfigureFunctionsWebApplication().ConfigureServices(service =>
    {
        service.AddHttpClient();
        service.AddLogging();
        // Add configurations according to your needs
    });
}
// Build and run the application
builder.Build().Run();

The program.cs file will replace any file that has the FunctionStartup attribute, which is typically a startup.cs file.

In places where your FunctionStartup code would reference IFunctionHostBuilder.Services, you can instead add statements within the.ConfigureService() method of the HostBuilder in your Program.cs.

Once you have moved everything from any existing FunctionStartup to the program.cs file, you can delete the FunctionStartup attribute and the class it was applied to.


Function Signature changes

Before (In-Process Model)


public static class Function1
{
    [FunctionName("Function1")]
    public static IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        return new OkObjectResult("Hello, Azure Functions!");
    }
}

After (Isolated Worker Model)


public class Function1
{
    private readonly ILogger<Function1> _logger;

    public Function1(ILogger<Function1> logger)
    {
        _logger = logger;
    }

    [Function("Function1")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
    {
        this._logger.LogInformation("C# HTTP trigger function processed a request.");
        var response = req.CreateResponse(HttpStatusCode.OK);
        await response.WriteStringAsync("Hello, Azure Functions!");
        return response;
    }
}

Updatinglocal.settings.json

Modify FUNCTIONS_WORKER_RUNTIME to dotnet-isolated.


{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

Publishing .NET 8 (Isolated) Azure Functions via Visual Studio

Follow these steps to deploy your function app to Azure using Visual Studio:

Download the Publish Profile

  • Open the Azure Portal.
  • Navigate to your Function App.
  • Go to Deployment Centre> Publish Profile and download the file.

Prepare Your Solution

  • Open your project in Visual Studio.
  • Set the build configuration to Release Mode.
  • Clean the solution to remove old build files.
  • Build the solution to ensure there are no errors.

Publish the Function App

  • In Solution Explorer, right-click on the function app project and select Publish.
  • Choose Import Profile as the publish target.
  • Browse and select the downloaded publish profile.
  • Click Publish and wait for the deployment to complete.

Once the process finishes, your function app is successfully deployed to Azure.


Upgrading in the Azure Portal

Upgrading your function app to the isolated model consists of the following steps:

Navigate to Settings > Environment Variables.

  • Update FUNCTIONS_EXTENSION_VERSION from ~3 to ~4.
  • Change FUNCTIONS_WORKER_RUNTIME to dotnet-isolated.

Under Settings > Configuration, ensure:

  • Runtime version is ~4.
  • General Settings .NET Version is .NET 8 Isolated.


Troubleshooting Error: “Building Configuration in an External Startup Class”Solution:

  • Go to Storage Account > Data Storage > Tables > AzureFunctionsDiagnosticEventsDate.
  • Delete or clear the table.


Conclusion

Upgrading to the .NET 8 Isolated Worker Model enhances the performance and maintainability of your Azure Functions. By following these steps, you ensure a smooth transition while leveraging the latest advancements in .NET and Azure Functions.

No comments:

Post a Comment