Search code examples
asp.net-coreazure-functions.net-6.0.net-8.0

Run time error after upgrading .net6 to .net8


After upgrading the .NET 6 Function App project to .NET 8, it built successfully. However, there are runtime errors in the console. I have successfully updated all relevant NuGet packages and dependencies. Here, I have attached the .csproj file before and after the upgrade, as well as the Startup.cs file.

This is a console error.

[2025-01-16T07:18:31.016Z] Error configuring services in an external startup class.
[2025-01-16T07:18:31.017Z] Error configuring services in an external startup class. Grpc.AspNetCore.Server: Could not load file or assembly 'Microsoft.AspNetCore.Routing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
[2025-01-16T07:18:31.073Z] A host error has occurred during startup operation '9765373b-601a-439f-a34a-cedf62160bf5'.
[2025-01-16T07:18:31.074Z] Microsoft.Azure.WebJobs.Script: Error configuring services in an external startup class. Grpc.AspNetCore.Server: Could not load file or assembly 'Microsoft.AspNetCore.Routing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
Value cannot be null. (Parameter 'provider')

This is a .csproj file before upgrading.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <UserSecretsId>fc83650f-36c6-4633-8e47-31d7168e76ae</UserSecretsId>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights" Version="2.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.8.1" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" />
    <PackageReference Include="PEMS.Core" Version="2.0.6" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\UserAccountService.Shared\UserAccountService.Shared.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

This is a .csproj file after upgrading.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <UserSecretsId>fc83650f-36c6-4633-8e47-31d7168e76ae</UserSecretsId>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.13.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.1" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.6.0" />
    <PackageReference Include="PEMS.Core" Version="2.0.6" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\UserAccountService.Shared\UserAccountService.Shared.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

This is a Startup.cs

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Identity;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using PEMS.Core;
using PEMS.Core.Configurations;
using PEMS.Core.Messaging;
using PEMS.UserAccountService.Shared.Contracts;
using PEMS.UserAccountService.Shared.Contracts.CoreData;
using PEMS.UserAccountService.Shared.Contracts.System;
using PEMS.UserAccountService.Shared.Models.DBModels;
using PEMS.UserAccountService.Shared.Models.Documents;
using PEMS.UserAccountService.Shared.Models.System;
using PEMS.UserAccountService.Shared.Services;
using PEMS.UserAccountService.Shared.Services.System;
using PEMS.UserAccountService.Shared.Stores;
using PEMS.UserAccountService.Shared.Support;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using static PEMS.Core.Messaging.Types.Constants;
using static PEMS.UserAccountService.Shared.Constants.Constants;
using IdentityUser = PEMS.UserAccountService.Shared.Models.Documents.IdentityUser;

[assembly: FunctionsStartup(typeof(PEMS.UserAccountService.Jobs.Startup))]
namespace PEMS.UserAccountService.Jobs
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var configBuilder = new ConfigurationBuilder()
                  .SetBasePath(Directory.GetCurrentDirectory())
                  .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
#if DEBUG
                  .AddUserSecrets(Assembly.GetExecutingAssembly(), false)
#endif
                  .AddEnvironmentVariables();
            var config = configBuilder.Build();
            config = configBuilder.Build();
            var appInsightsInstrumentationKey = config.GetValue<string>("ApplicationInsightsInstrumentationKey");
            var telemetryClientConfig = new TelemetryConfiguration { InstrumentationKey = appInsightsInstrumentationKey };

            var environment = config.GetValue<string>("Environment");

            var dbConnectionSection = config.GetSection("PEMS-UserAccount-DbConnection");
            DbInfo dbConnection = new DbInfo();
            dbConnectionSection.Bind(dbConnection);

            var systemHostUrl = config.GetValue<string>("SystemHostUrl");
            var aiHostUrl = config.GetValue<string>("AIHostUrl");
            URLInfo urlInfo = new URLInfo
            {
                SystemHostUrl = systemHostUrl,
                AIHostUrl = aiHostUrl
            };

            var systemDefaultLanguage = config.GetValue<string>("SystemDefaultLanguage");
            SystemInfo systemInfo = new SystemInfo
            {
                SystemDefaultLanguage = systemDefaultLanguage
            };

            builder.Services.AddSingleton(s => dbConnection);
            builder.Services.AddSingleton(s => urlInfo);
            builder.Services.AddSingleton<IDocumentDbService, CosmosDbService>();
            builder.Services.AddSingleton(s => new SystemInfo { Product = PEMSConstants.Product, Environment = environment });
            builder.Services.AddSingleton<ITelemetryInitializer, SystemTelemetryInitializer>();
            builder.Services.AddMemoryCache();

            builder.Services.AddScoped(s => new TelemetryClient(telemetryClientConfig));
            builder.Services.AddScoped<ILoggerService, ApplicationInsightsLoggerService>();
            builder.Services.AddScoped<RequestContext>();
            builder.Services.AddScoped<ICustomerDataContext, CustomerDataContext>();
            builder.Services.AddScoped<ISystemDataContext, SystemDataContext>();
            builder.Services.AddScoped<IEventNotificationService, EventNotificationService>();
            builder.Services.AddScoped<IUserService, UserService>();
            builder.Services.AddScoped<ICoreDataService, CoreDataService>();
            builder.Services.AddScoped<IIdentityService, IdentityService>();
            builder.Services.AddScoped<IUserPermissionService, UserPermissionService>();
            builder.Services.AddScoped<IPermissionService, PermissionService>();
            builder.Services.AddScoped<ILookupService, LookupService>();
            builder.Services.AddScoped<ICustomerDataContextFactory, CustomerDataContextFactory>();
            builder.Services.AddScoped<ICustomTicketStore, InMemoryTicketStore>();
            builder.Services.AddScoped<ICustomerService, CustomerService>();
            builder.Services.AddScoped<IAIDeviceService, AIDeviceService>();
            builder.Services.AddScoped<IConfigurationService, ConfigurationService>();

            var serviceBusOperationTimeoutInSeconds = config.GetValue<int>("ServiceBusOperationTimeoutInSeconds");

            builder.Services.AddSystemMessagePublishing(
                                                config.GetValue<string>("ServiceBusConnectionString"),
                                                config.GetValue<string>("GeneralTopicName"),
                                                string.Empty,
                                                ServiceOrigins.UserAccountService,
                                                TimeSpan.FromSeconds(serviceBusOperationTimeoutInSeconds));

            builder.Services.AddScoped<UserManager<IdentityUser>>();
            builder.Services.AddScoped<IUserStore<IdentityUser>, DocumentDbUserStore<IdentityUser>>();
            builder.Services.AddScoped<IRoleStore<DocumentDbIdentityRole>, DocumentDbRoleStore<DocumentDbIdentityRole>>();
            builder.Services.AddScoped<ILookupNormalizer, LookupNormalizer>();


            JsonConvert.DefaultSettings = () =>
            {
                return new JsonSerializerSettings()
                {
                    Converters = new List<JsonConverter>() { new JsonClaimConverter(), new JsonClaimsPrincipalConverter(), new JsonClaimsIdentityConverter(), new JsonAuthenticationTicketConverter() }
                };
            };
        }
    }
}

Solution

  • As I mentioned in the comments, you have to add the application setting "FUNCTIONS_INPROC_NET8_ENABLED": "1" in local.settings.json to resolve the error Could not load file or assembly 'Microsoft.AspNetCore.Routing.

    Updated your local.setting.json as below:

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_INPROC_NET8_ENABLED": "1",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "Environment": "LOCAL",
        "GeneralTopicName": "sbt-general",
        "UserAccountCrudEventsSubscriptionName": "useraccount-crud",
        "ApplicationInsightsInstrumentationKey": "",
        "KeyVaultDomain": "",
        "ServiceBusConnectionString": "connectionstring",
        "SystemHostUrl": "http://localhost:4200/#",
        "AIHostUrl": "http://localhost:7075/#",
        "SystemDefaultLanguage": "en-AU"
      },
      "PEMS-UserAccount-DbConnection": {
        "DatabaseId": "pemsdb",
        "DefaultCollectionId": "useraccount_default"
      },
      "ServiceBusOperationTimeoutInSeconds": 60
    }
    

    Console Output:

    Functions:
    
            Function1: serviceBusTrigger
    
    For detailed output, run func with --verbose flag.
    [2024-01-17T08:41:54.990Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
    [2024-01-17T08:42:15.389Z] Executing 'Function1' (Reason='(null)', Id=b57524a6-4fb8-4586-9bfb-c88e23d137bb)
    [2024-01-17T08:42:15.394Z] Trigger Details: MessageId: 129a51488e34478db8ff88c43308da8b, SequenceNumber: 1, DeliveryCount: 1, EnqueuedTimeUtc: 2024-03-31T10:42:12.1620000+00:00, LockedUntilUtc: 2024-03-31T10:43:12.2400000+00:00, SessionId: (null)
    [2024-01-17T08:42:15.433Z] C# ServiceBus topic trigger function processed message: Hello
    [2024-01-17T08:42:15.490Z] Executed 'Function1' (Succeeded, Id=b57524a6-4fb8-4586-9bfb-c88e23d137bb, Duration=205ms)