Reputation: 565
I have the following activity function:
[FunctionName("LoadSubscriptionAnalytics_Activity")]
public static async Task<IActionResult> RunActivity([ActivityTrigger] ILogger log
)
{
log.LogInformation("Activity function");
}
Log.LogInformation fails with error: Value cannot be null. (Parameter 'logger')
The logger works in my orchestrator function:
[FunctionName("LoadSubscriptionAnalytics_Orchestrator")]
public static async Task<List<Task<IActionResult>>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var outputs = new List<Task<IActionResult>>();
log.LogInformation("Orchestrator function");
outputs.Add(await context.CallActivityAsync<Task<IActionResult>>("LoadSubscriptionAnalytics_Activity", null));
return outputs;
}
Why is this dependency injection not working? I am using Functions V2 with .Net Core 3.1
Upvotes: 1
Views: 8897
Reputation: 565
I managed to resolve it, had to pass a context object -IDurableOrchestrationContext context from the orchestrator so that the activity function could detect it as a parameter. My code is:
Orchestrator
[FunctionName("LoadSubscriptionAnalytics_Orchestrator")]
public static async Task<List<Task<IActionResult>>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var outputs = new List<Task<IActionResult>>();
log = context.CreateReplaySafeLogger(log);
log.LogInformation("Calling LoadSubscriptionAnalytics_Activity");
outputs.Add(await context.CallActivityAsync<Task<IActionResult>>("LoadSubscriptionAnalytics_Activity", context));
log.LogInformation("Done !");
return outputs;
}
Activity
[FunctionName("LoadSubscriptionAnalytics_Activity")]
public static async Task<IActionResult> RunActivity([ActivityTrigger] IDurableActivityContext activityContext, ILogger log
)
{
//This works
log.LogInformation("Activity function");
}
Thanks
Upvotes: 2
Reputation: 155145
LogInformation
is an extension-method for ILogger
, defined in Microsoft.Extensions.Logging.Abstractions.dll
.
Because it's an extension-method rather than a real instance method, when it's invoked it's the same as a static
method call, and the .NET runtime will not check that the subject/instance reference is null
or not - so you don't get a NullReferenceException
.
Which can be useful, actually - I have my own utility library with a syntactically-succinct extension-method alternative to String.IsNullOrWhiteSpace
:
// Declaration:
public static Boolean IsSet( this String str ) => !String.IsNullOrWhiteSpace( str ):
// Usage:
String x = null;
Console.WriteLine( x.IsSet() ); // Prints "false" with no NullReferenceException
So in your case, when log.LogInformation("Activity function");
runs, the log
argument to RunActivity
is null
.
I assume log
is intended to be optional - so use ?.
to skirt around it - or if it's required then throw your own ArgumentNullException
exception:
[FunctionName("LoadSubscriptionAnalytics_Activity")]
public static async Task<IActionResult> RunActivity( [ActivityTrigger] ILogger log )
{
log?.LogInformation("Activity function");
}
[FunctionName("LoadSubscriptionAnalytics_Activity")]
public static async Task<IActionResult> RunActivity( [ActivityTrigger] ILogger log )
{
if( log is null ) throw new ArgumentNullException( nameof(log) );
log.LogInformation("Activity function");
}
log
parameter's argument is null
in the first place - have you configured your DI container correctly in ConfigureServices
? I'll admit I'm not too familiar with Azure Durable Functions - but in .NET in general DI is only set-up for constructors, not static methods - though some environments do allow DI use for static method parameters.Upvotes: 0