josh
josh

Reputation: 1271

Azure function dependency injection failures when multiple functions deployed

I am having a problem where I have multiple azure functions deployed on a single app service and I am getting dependency injection errors.

This is the exception from the Azure Function portal view:

2020-02-19T06:34:33.432 [Error] Executed 'Logger' (Failed, Id=edfbcc63-09b6-4f9e-8ee3-81fe50fd9412)
System.InvalidOperationException : Unable to resolve service for type 'Cloud.Services.Storage.Azure.IAzureTableStorageService' while attempting to activate 'Cloud.Web.AzureFunctions.Functions.Logger.Logger'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp,Type type,Type requiredBy,Boolean isDefaultParameterRequired)
   at lambda_method(Closure ,IServiceProvider ,Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider serviceProvider) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs : 37
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs : 32
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs : 20
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create(IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs : 26
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs : 44
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize() at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs : 846
   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance,CancellationToken cancellationToken) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs : 116

Code:

Function Definition:

[assembly: WebJobsStartup(typeof(FunctionStartUp))]
namespace Cloud.Web.AzureFunctions.Functions.Logger
{
    public class Logger
    {
        private readonly IAzureTableStorageService _azureTableStorageService;
        public Logger(IAzureTableStorageService azureTableStorageService)
        {
            _azureTableStorageService = azureTableStorageService;
        }

        [FunctionName("Logger")]
        public async Task Run(
            [ServiceBusTrigger("logger", Connection = @"ServiceBusConnectionString")]
            EntityLogEntry myQueueItem,
            ILogger log,
            ExecutionContext context)
        {...}

Startup:

public class FunctionStartUp : IWebJobsStartup
{
    public static ServiceProvider Container { get; private set; }

    public void Configure(IWebJobsBuilder builder)
    {
        Container = CoreAppModule.ConfigureServices(builder.Services).BuildServiceProvider();
    }
}
public class CoreAppModule
    {
        public static IServiceCollection ConfigureServices(IServiceCollection services)
        {
            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("local.settings.json", true) //when deployed, all application settings must be stored in azure app configuration
                .AddEnvironmentVariables()
                .Build();

            services.SetupConnectionStrings(config);
            services.AddOptions();
            services.SetupAutoMapper();
            services.SetupMongoRepositories(config);
            services.SetupDbContextsEFCore();
            services.SetupDataServices(config);
            services.SetupServices(config);
            services.SetupInMemoryCache();
            services.SetupIntegrationServices(config);
            services.SetupStorageServices(config);
            services.SetupCrypto(config);
            services.SetupIntegrationLibraryServices(config);
            services.SetupFtpConnectionDetails(config);
            services.SetupServiceBus(config);
            services.SetupStartupInitialization(config);

            return services;
        }
    }

Dependencies:

enter image description here

Portal Settings:

enter image description here enter image description here

Upvotes: 0

Views: 2065

Answers (2)

shyambabu
shyambabu

Reputation: 163

There is file called extensions.json in the bin folder. Your startup calls register in that file. Whichever function app deployed latest, that function's startup call will be replaced with earlier function's startup call. So, you need to take an action that all the functions' startup calls will be registered in this file.

enter image description here

enter image description here

Upvotes: 1

Raffy
Raffy

Reputation: 605

Seems like you haven't injected IAzureTableStorageService properly in your Startup class hence the DI can't find it. Reference the project where IAzureTableStorageService is located, add something like this in your Startup class:

services.AddTransient<IAzureTableStorageService, AzureTableStorageService>();

where AzureTableStorageService is your class that implements IAzureTableStorageService.

Upvotes: 0

Related Questions