Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection injecting null when missing registration in Azure functions

I'm getting null injected into my constructor that has a dependency which I forgot to register.

In the below example dependency would be null when you forget to register IDepencency in the startup class

public class AzureFunction {
    public AzureFunction(IDepencency dependency) {

    }
}

I expected it to work the same as in .net core DI.

Is this expected behavior? And can I maybe change a setting to enable throwing exceptions?

Edit:

After reading HariHaran's answer, I realized it's only happening in a sub-dependency. This is a reproducible example:

public interface IClass1 { }

public class Class1 : IClass1
{
    private readonly IClass2 _class2;

    public Class1(IClass2 class2)
    {
        _class2 = class2; // This will be null
    }
}

public interface IClass2 { }

public class Class2 : IClass2 { }

public class Function1
{
    private readonly IClass1 _class1;
    public Function1(IClass1 class1)
    {
        _class1 = class1;
    }

    [FunctionName("Function1")]
    public async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous,"post", Route = null)]
        HttpRequestMessage req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        return req.CreateResponse(HttpStatusCode.Accepted);

    }
}

And put this in the functionsStartup:

[assembly: FunctionsStartup(typeof(Startup))]
namespace FunctionApp2
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IClass1, Class1>();
            //builder.Services.AddSingleton<IClass2, Class2>(); // Leave this commented
        }
    }

}
like image 683
Zenuka Avatar asked Sep 18 '19 11:09

Zenuka


Video Answer


2 Answers

If the framework is not throwing the exception, then you can do it manually within the function's constructor.

For example

public class AzureFunction {
    private readonly IDependency _dependency;

    public AzureFunction(IDepencency dependency) {
        _dependency = dependency ?? throw new ArgumentNullException(nameof(dependency));
    }

    //...
}
like image 130
Phat Huynh Avatar answered Oct 16 '22 09:10

Phat Huynh


No this is not the expected behaviour. The func host by default will throw

Unable to resolve service for type 'FunctionApp2.IClass1' while attempting to activate 'FunctionApp2.Function1'.

Here's the simple reproducable piece of code.

public class Function1
{
    private readonly IClass1 _class1;
    public Function1(IClass1 class1)
    {
        _class1 = class1;
    }
    [FunctionName("Function1")]
    public async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous,"post", Route = null)]
        HttpRequestMessage req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        return req.CreateResponse(HttpStatusCode.Accepted);

    }
}

In the functionsStartup i commented my registration

[assembly: FunctionsStartup(typeof(Startup))]
namespace FunctionApp2
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            //builder.Services.AddSingleton<IClass1, Class1>();

        }
    }

}
like image 1
HariHaran Avatar answered Oct 16 '22 09:10

HariHaran