Describe the bug
Null Exception during Dependency Injection within Azure Functions. Working in 10.0.1 only.
To Reproduce
Using Repository located https://github.com/OneCyrus/GraphQL-AzureFunctions-HotChocolate
Steps to reproduce the behavior:
{
droid(id:2000) {
name
}
}
{
"data": {},
"extensions": {},
"errors": [
{
"message": "Unexpected Execution Error",
"code": null,
"path": null,
"locations": [],
"exception": {
"ClassName": "System.NullReferenceException",
"Message": "Object reference not set to an instance of an object.",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": " at lambda_method(Closure , IResolverContext )\r\n at DryIoc.Factory.<>c__DisplayClass26_0.<ApplyReuse>b__2() in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6596\r\n at DryIoc.Scope.TryGetOrAdd(ImMap`1 items, Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 7840\r\n at DryIoc.Scope.GetOrAdd(Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 7825\r\n at DryIoc.Factory.ApplyReuse(Expression serviceExpr, Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6595\r\n at DryIoc.Factory.GetExpressionOrDefault(Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6555\r\n at DryIoc.Factory.GetDelegateOrDefault(Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6625\r\n at DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 210\r\n at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 195\r\n at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.GetService(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\JobHostServiceProvider.cs:line 101\r\n at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.GetService(Type serviceType) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\JobHostServiceProvider.cs:line 79\r\n at lambda_method(Closure , IServiceProvider , QueryDelegate )\r\n at HotChocolate.Execution.ClassMiddlewareFactory.<>c__DisplayClass0_0`1.<Create>b__1(IServiceProvider s, QueryDelegate n)\r\n at HotChocolate.Execution.ClassMiddlewareFactory.<>c__DisplayClass2_0`1.<CreateDelegate>b__0(IQueryContext context)\r\n at HotChocolate.Execution.ExceptionMiddleware.InvokeAsync(IQueryContext context)",
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": null,
"HResult": -2147467261,
"Source": "Anonymously Hosted DynamicMethods Assembly",
"WatsonBuckets": null
},
"extensions": {
"message": "Object reference not set to an instance of an object.",
"stackTrace": " at lambda_method(Closure , IResolverContext )\r\n at DryIoc.Factory.<>c__DisplayClass26_0.<ApplyReuse>b__2() in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6596\r\n at DryIoc.Scope.TryGetOrAdd(ImMap`1 items, Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 7840\r\n at DryIoc.Scope.GetOrAdd(Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 7825\r\n at DryIoc.Factory.ApplyReuse(Expression serviceExpr, Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6595\r\n at DryIoc.Factory.GetExpressionOrDefault(Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6555\r\n at DryIoc.Factory.GetDelegateOrDefault(Request request) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 6625\r\n at DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 210\r\n at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\DryIoc\\Container.cs:line 195\r\n at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.GetService(Type serviceType, IfUnresolved ifUnresolved) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\JobHostServiceProvider.cs:line 101\r\n at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.GetService(Type serviceType) in C:\\azure-webjobs-sdk-script\\src\\WebJobs.Script.WebHost\\DependencyInjection\\JobHostServiceProvider.cs:line 79\r\n at lambda_method(Closure , IServiceProvider , QueryDelegate )\r\n at HotChocolate.Execution.ClassMiddlewareFactory.<>c__DisplayClass0_0`1.<Create>b__1(IServiceProvider s, QueryDelegate n)\r\n at HotChocolate.Execution.ClassMiddlewareFactory.<>c__DisplayClass2_0`1.<CreateDelegate>b__0(IQueryContext context)\r\n at HotChocolate.Execution.ExceptionMiddleware.InvokeAsync(IQueryContext context)"
}
}
],
"contextData": {}
}
Expected behavior
I am not sure what fundamental changes occur in between 10.0.1 and 10.2.0, but something is affecting the DI stopping it from working in Azure Functions.
Desktop (please complete the following information):
Additional context
Here are some of the variables I see when the exception is encountered.

My guess is there is a change in what this bit of code does which is causing the DI issues
builder.Services.AddGraphQL(sp => SchemaBuilder.New()
.AddServices(sp)
.AddQueryType<QueryType>()
.AddType<HumanType>()
.Create());
Any pointers or assistance would be greatly apreciated
Thanks, Basil
@OneCyrus had similar issue, maybe he knows more
the problem is likely the scoped DI which has a different lifetime in AzF: https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#service-lifetimes
we discussed this here: https://hotchocolategraphql.slack.com/archives/CD9TNKT8T/p1569335037212400
we discussed this here: https://hotchocolategraphql.slack.com/archives/CD9TNKT8T/p1569335037212400
I dont have access to Slack. Could you provide a quick summary?
Is it an issue with how HC adds the GraphQL services during Configure?

i just gave this one a try again. and it doesn't look like the azure functions DI behaves incorrectly. the scoped instances are created correctly. there's also a sample on the AzF repo which shows this:
https://github.com/Azure/azure-functions-dotnet-extensions/tree/master/src/samples/DependencyInjection/Scopes
(though i had to update the dependencies to get it up and running)
it looks like there's really an issue where hotchocolate behaves strange in combination with AzF DI.
Hm... @michaelstaib could this be related to the custom service factory?
Somehow loosing state
I think the issue is how we build the execution builder. We will fix that in 11 since we will take apart the whole execution. But first I want to focus more on StrawberryShake and Visual Studio integration.
Once Rafi is done with the first public preview of bcp we can start work on this.
Ok. So @OneCyrus and I were debugging a bit.
The functions really behave strange. We could narrow down the issue and think it is related to the DI more specific to the DI injecting this class. https://github.com/ChilliCream/hotchocolate/blob/master/src/Core/Core/Execution/Middleware/ParseQueryMiddleware.cs
The DI containers fails when it tries to inject IDocumentHashProvider documentHashProvider
This behavior is easily reproducible by registering the IDocumentHashProvider in the function startup:
builder.Services.AddSingleton<IDocumentHashProvider>((sp) => new MD5DocumentHashProvider());
and then fetch the dependency in function method. It doesn't matter if you do it with ctor injection, over the contextAccessor, or with the HTTPContext in the Request, it all fails :
var services = req.HttpContext.RequestServices;
var test = services .GetService<ReviewRepository>(); // works
var test = services .GetService<IDocumentHashProvider>(); // 馃挘
And now it becomes really weird.
We registered an instance. As we register a singleton i really expect this instance to be returned.
In fact, the DI does try to activate the dependency via activator
MD5DocumentHashProvider has two constructors. One without a parameter and one with a parameter. I don't know about the ctor scoring algorithm of this DI implementation. but it chooses the wrong one.

Well.. In the end we don't really need this instance anyway. If the DI injects null this case is handled in the ctor of ParseQueryMiddleware.cs. But the DI Container blows up as soon as it doesnt find a reference.
so GetService on their container is really GetRequiredService?
it looks like that. GetService stops the execution of the function when it doesn't find something and doesn't just return null. though it's not the implementation of the DI as it's the same Microsoft.Extension.DependencyInjection package which handles this.
though it's probably just because of using the wrong ctor for the HashProvider
hm.. it's not supposed to be created by the DI. The DI should just resolve it :D
looks like manually registering the HashDocumentProvider after the GraphQL-initialization fixed the issue.
https://github.com/OneCyrus/GraphQL-AzureFunctions-HotChocolate/commit/a37c68a3384e3e47ebad7796318b0cad9b809338#diff-fbd03c53f6f1dc7701583e41f0cda5c8
the feat_nativeDI branch works now with the latest HC version:
https://github.com/OneCyrus/GraphQL-AzureFunctions-HotChocolate
Thank you. I have been able to get it working using the suggested approach for now.
Keep me posted if it gets fixed in V 11.
Thanks
@michaelstaib do fix this here: https://github.com/ChilliCream/hotchocolate/blob/cf600304845e716fb9dfacdce491bc59c31bf1b8/src/Core/Core/Execution/Extensions/QueryExecutionBuilderExtensions.cs#L706
or do we want to remove the unused empty constructor?
This one is now merged and will be part of 10.3.4
Most helpful comment
looks like manually registering the HashDocumentProvider after the GraphQL-initialization fixed the issue.
https://github.com/OneCyrus/GraphQL-AzureFunctions-HotChocolate/commit/a37c68a3384e3e47ebad7796318b0cad9b809338#diff-fbd03c53f6f1dc7701583e41f0cda5c8
the feat_nativeDI branch works now with the latest HC version:
https://github.com/OneCyrus/GraphQL-AzureFunctions-HotChocolate