question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Constructor dependency injection for web jobs causes an error in 3.0.0-rc1

See original GitHub issue

Repro steps

  1. Add interface to be injected into the functions.
  2. Add interface to the functions constructor.
  3. Run the web job.

Expected behavior

Programme to run with the injected interface working.

Actual behavior

Webjob errors with “Object reference not set to an instance of an object”

Related information

Provide any related information Error

fail: Host.Results[0] Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.ProcessWorkItem_ServiceBus —> System.NullReferenceException: Object reference not set to an instance of an object. at lambda_method(Closure , Functions , Object[] ) at Microsoft.Azure.WebJobs.Host.Executors.VoidTaskMethodInvoker 2.InvokeAsync(TReflected instance, Object[] arguments) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\VoidTaskMethodInvoker.cs:line 20 at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker 2.InvokeAsync(Object instance, Object[] arguments) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 63 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker, ParameterHelper parameterHelper, CancellationTokenSource timeoutTokenSource, CancellationTokenSource functionCancellationTokenSource, Boolean throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 562 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance instance, ParameterHelper parameterHelper, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 509 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstance instance, ParameterHelper parameterHelper, IFunctionOutputDefinition outputDefinition, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 445 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstance instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 249 — End of inner exception stack trace — at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstance instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 293 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance functionInstance, CancellationToken cancellationToken) in azure-webjobs-sdk-3.0.0-rc1\azure-webjobs-sdk-3.0.0-rc1\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 89

Program.cs

public static async Task Main(string[] args)
{
    var builder = new HostBuilder()
        .UseEnvironment("Development")
        .ConfigureWebJobs(b =>
        {
            b.AddDashboardLogging()
            .AddAzureStorageCoreServices()
            .AddAzureStorage()
            .AddServiceBus()
            .AddEventHubs()
            .AddExecutionContextBinding();
        })
        .ConfigureAppConfiguration(b =>
        {
            // Adding command line as a configuration source
            b.AddCommandLine(args);
        })
        .ConfigureServices((hostContext, services) => {
            services.AddSingleton<IJobActivator>(new JobActivator(services.BuildServiceProvider()));
            services.AddScoped<Functions, Functions>();
            services.AddSingleton<IWriteText, WriteText>(); })
        .ConfigureLogging((context, b) =>
        {
            b.SetMinimumLevel(LogLevel.Debug);
            b.AddConsole();
            // If this key exists in any config, use it to enable App Insights
            string appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
            if (!string.IsNullOrEmpty(appInsightsKey))
            {
                b.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
            }
        })
        .UseConsoleLifetime();

    var host = builder.Build();
    using (host)
    {
        await host.RunAsync();
    }
}

Functions.cs

public class Functions
{
    private readonly IWriteText _writeText;

    public Functions(IWriteText writeText)
    {
        _writeText = writeText;
    }

    public async Task ProcessWorkItem_ServiceBus(
        [ServiceBusTrigger("%queue%", Connection = "AzureWebJobsServiceBus")] string item, ILogger log)
    {
        log.LogInformation(_writeText.PopPop());
    }
}

IWriteText.cs

public interface IWriteText
{
    string PopPop();
}

public class WriteText : IWriteText
{
    public string PopPop()
    {
        return "Pop Pop!";
    }
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

7reactions
johnkwaterscommented, Oct 13, 2018

Amy news on first class DI support, and documentation?

1reaction
dotnetjunkiecommented, May 17, 2019

Hi @mathewc, @fabiocav’s change does indeed fix the problem. Wonder how I missed that. When implementing an IJobActicatorEx, the supplied IFunctionInstanceEx contains a IServiceProvider property, which is the actual scoped provider. This means that every DI Container should now be able to plugin to this model. Here’s the Simple Injector verion:

public class SimpleInjectorJobActivator : IJobActivatorEx
{
    private readonly Container container;

    public SimpleInjectorJobActivator(Container container) => this.container = container;

    public T CreateInstance<T>(IFunctionInstanceEx functionInstance)
    {
        var disposer = functionInstance.InstanceServices.GetRequiredService<ScopeDisposable>();
        this.disposer.Scope = AsyncScopedLifestyle.BeginScope(this.container);
        // Scopes in Simple Injector are ambient; you always resolve from the container
        return (T)this.container.GetInstance(typeof(T));
    }

    // Ensures a created Simple Injector scope is disposed at the end of the request
    public sealed class ScopeDisposable : IDisposable
    {
        public Scope Scope { get; set; }
        public void Dispose() => this.Scope?.Dispose();
    }
}

By using the following configuration, jobs can be resolved using Simple Injector:

services
    .AddScoped<SimpleInjectorJobActivator.ScopeDisposable>()
    .AddSingleton<IJobActivator>(new SimpleInjectorJobActivator(container));

Awesome work @fabiocav.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Webjobs Method Indexing - Dependency Injection ...
WebJobs.Host.Indexers.FunctionIndexingException: 'Error indexing method 'Functions.ProcessQueueMessage'' InvalidOperationException: Cannot bind ...
Read more >
Use dependency injection in .NET Azure Functions
The use of constructor injection requires that you do not use static classes for injected services or for your function classes.
Read more >
Table of Contents - Micronaut Documentation
The Micronaut framework aims to provide all the tools necessary to build JVM applications including: Dependency Injection and Inversion of Control (IoC). Aspect ......
Read more >
5. The IoC container
IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they...
Read more >
Scheduled job not running with dependency injection for ...
I have a sercvice injected into scheduled job constructor. The job works fine if I manually trigger the job. code snipest:
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found