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);
}
}
}
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)