Search code examples
c#.netazure-functionsazure-functions-isolated

Azure Functions - Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=8.0.0.0


I'm attempting to create an Azure Function with a Service Bus Trigger. It builds fine locally however when I come to trying to run it, I receive this error:

[2024-11-28T12:47:02.953Z] A host error has occurred during startup operation '2fe67e9d-b8ad-4ee6-9603-18ba874fbe69'.
[2024-11-28T12:47:02.953Z] Microsoft.Azure.WebJobs.Script: Error building configuration in an external startup class. TransactionEventsProcessor: Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.

I have the following nuget packages installed:

<PackageReference Include="Azure.Messaging.EventHubs" Version="5.11.1" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.EventHubs" Version="6.2.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.14.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.3.2" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" />

If I also install Microsoft.Extensions.Configuration.Abstractions, I get the same error message. Any suggestions on how to resolve this error?

Startup.cs class:

public class Startup : FunctionsStartup
{
    /// <inheritdoc />
    public override void Configure(IFunctionsHostBuilder builder)
    {
        var configuration = builder.GetContext().Configuration;

        builder.Services.AddSingleton<IMessageMapper, MessageMapper>();
    }

    /// <inheritdoc />
    public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
    {
#if DEBUG
        builder.ConfigurationBuilder
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("local.settings.json", true);
#else
    AzureAppConfig.Extensions.DependencyInjectionExtensions
        .AddAzureAppConfig(builder.ConfigurationBuilder)
        .AddEnvironmentVariables();
#endif
        base.ConfigureAppConfiguration(builder);
    }
}

Function code:

public class IntegrationFunction
{
    /// <summary>
    /// The message mapper
    /// </summary>
    private IMessageMapper messageMapper;

    /// <summary>
    /// Polling integration.
    /// </summary>
    /// <param name="message">The message</param>
    /// <param name="logger">The logger.</param>
    /// <param name="messageActions">The message actions</param>
    /// <param name="queuedMessageClient">The mainframe queued message client</param>
    /// <param name="messageMapper">The message mapper</param>
    [FunctionName("IntegrationFunction")]
    [return: ServiceBus("%Transactions:SB:Transactions:ProcessorUpdateQueue%", Connection = "Transactions:SB:Transactions")]
    public async Task<ServiceBusMessage> Run(
        [ServiceBusTrigger(
            "%Transactions:SB:Transactions:ReceiveTopic%",
            "%Transactions:SB:Transactions:TransactionEventsTopicSubscription%",
            Connection = "Transactions:SB:Transactions")]
        ServiceBusReceivedMessage message,
        ILogger logger,
        ServiceBusMessageActions messageActions,
        IMainframeQueuedMessageClient queuedMessageClient,
        IMessageMapper messageMapper,
        IConfiguration configuration)
    {
        try
        {
            var retailTransaction = JsonConvert.DeserializeObject<RetailTransaction>(message.Body.ToString(), JsonSerialisationUtils.SerialiserSettings);
            if (retailTransaction == null)
                throw new TransactionDeserialisationException();

            if (retailTransaction.PollingEvents == null)
                return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);

            if (configuration?[Constants.DisableSendToMainframe] == null || configuration[Constants.DisableSendToMainframe].ToLowerInvariant().Equals("false"))
            {
                logger.LogWarning($"Transaction event messages for '{retailTransaction.TransactionNumber}' will not be sent due to app configuration {Constants.DisableSendToMainframe} being enabled" );
                return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);
            }

            return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);
        }
        catch (Exception ex)
        {
            return ((RetailTransaction)null).GetServiceBusMessage(CompletionResults.CompletedWithError, errorMessage: ex.Message);
        }
    }
}

Solution

  • I am using the same code alike you with few modification in it.

    I have below codes in the mentioned files in .NET8 in-process Service Bus topic triggered function.

    Function code :-

    public class IntegrationFunction
    {
        private readonly IMessageMapper _messageMapper;
        private readonly IConfiguration _configuration;
    
        public IntegrationFunction(IMessageMapper messageMapper, IConfiguration configuration)
        {
            _messageMapper = messageMapper;
            _configuration = configuration;
        }
    
        [FunctionName("IntegrationFunction")]
    
        [return: ServiceBus("%Transactions:SB:Transactions:ProcessorUpdateQueue%", Connection = "Transactions:SB:Transactions")]
        public async Task<ServiceBusMessage> Run(
        [ServiceBusTrigger(
            "%Transactions:SB:Transactions:ReceiveTopic%",
            "%Transactions:SB:Transactions:TransactionEventsTopicSubscription%",
            Connection = "Transactions:SB:Transactions")]
        ServiceBusReceivedMessage message,
        ILogger logger,
        ServiceBusMessageActions messageActions)
        {
            try
            {
                var retailTransaction = JsonConvert.DeserializeObject<RetailTransaction>(message.Body.ToString(), JsonSerialisationUtils.SerialiserSettings);
                if (retailTransaction == null)
                    throw new TransactionDeserialisationException();
    
                if (retailTransaction.PollingEvents == null)
                    return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);
    
                if (_configuration?[Constants.DisableSendToMainframe] == null || _configuration[Constants.DisableSendToMainframe].ToLowerInvariant().Equals("false"))
                {
                    logger.LogWarning($"Transaction event messages for '{retailTransaction.TransactionNumber}' will not be sent due to app configuration {Constants.DisableSendToMainframe} being enabled");
                    return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);
                }
    
                return retailTransaction.GetServiceBusMessage(CompletionResults.Completed);
            }
            catch (Exception ex)
            {
                return ((RetailTransaction)null).GetServiceBusMessage(CompletionResults.CompletedWithError, errorMessage: ex.Message);
            }
        }
    }
    

    Startup :-

    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using System.IO;
    
    [assembly: FunctionsStartup(typeof(_79233974.Startup))]
    
    namespace _79233974
    {
        public class Startup : FunctionsStartup
        {
            public override void Configure(IFunctionsHostBuilder builder)
            {
                builder.Services.AddSingleton<IMessageMapper, MessageMapper>();
            }
    
            public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
            {
                FunctionsHostBuilderContext context = builder.GetContext();
    
                builder.ConfigurationBuilder
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("local.settings.json", true)
                    .AddEnvironmentVariables();
    
            }
        }
    }
    

    .csproj :-

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <AzureFunctionsVersion>v4</AzureFunctionsVersion>
        <RootNamespace>_79233974</RootNamespace>
      </PropertyGroup>
      <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
        <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.16.4" />
        <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.6.0" />
      </ItemGroup>
      <ItemGroup>
        <None Update="host.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
        <None Update="local.settings.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
          <CopyToPublishDirectory>Never</CopyToPublishDirectory>
        </None>
      </ItemGroup>
    </Project>
    

    By having the above given codes, I am able to execute the function successfully in local.

    Azure Functions Core Tools
    Core Tools Version:       4.0.6518 Commit hash: N/A +74ed9095fdd6c5326276aae6b8a7d41ccbdeb6aa (64-bit)
    Function Runtime Version: 4.35.4.23179
    
    [2024-12-02T05:30:22.442Z] Found C:\Users\****\79233974\79233974.csproj. Using for user secrets file configuration.
    
    Functions:
    
            IntegrationFunction: serviceBusTrigger
    
    For detailed output, run func with --verbose flag.
    [2024-12-02T05:30:30.548Z] Host lock lease acquired by instance ID '0000000000000000000000000D2022A4'.
    [2024-12-02T05:30:34.599Z] Executing 'IntegrationFunction' (Reason='(null)', Id=cb10e66e-0663-465b-a238-4d2628bb9688)
    [2024-12-02T05:30:34.604Z] Trigger Details: MessageId: 43a71be732f942baa3983e30f37edcb6, SequenceNumber: 2, DeliveryCount: 1, EnqueuedTimeUtc: 2024-12-02T05:30:34.1790000+00:00, LockedUntilUtc: 2024-12-02T05:31:34.1950000+00:00, SessionId: (null)
    [2024-12-02T05:30:34.646Z] Transaction event messages for '12345' will not be sent due to app configuration DisableSendToMainframe being enabled
    [2024-12-02T05:30:35.799Z] Executed 'IntegrationFunction' (Succeeded, Id=cb10e66e-0663-465b-a238-4d2628bb9688, Duration=1326ms)
    

    enter image description here