StreamResult attribute leads to abnormal IResolverContext data
Product
Hot Chocolate
Version
13.8.1
Link to minimal reproduction
None
Steps to reproduce
- Define a GraphQL query that uses the
[StreamResult]attribute. - Inject
IResolverContextinto the query method. - Execute the query to initiate the stream.
- Observe that the
IResolverContextcontains abnormal data, despite not being null.
What is expected?
The IResolverContext should contain accurate and expected data, reflecting the correct state of the HTTP context and user session.
What is actually happening?
The IResolverContext is populated with abnormal or incorrect data when using the [StreamResult] attribute.
Relevant log output
- context {HotChocolate.Execution.Processing.MiddlewareContext} HotChocolate.Resolvers.IResolverContext {HotChocolate.Execution.Processing.MiddlewareContext}
Arguments null System.Collections.Generic.IReadOnlyDictionary<string, HotChocolate.Resolvers.ArgumentValue>
+ ContextData '((HotChocolate.Execution.Processing.MiddlewareContext)context).ContextData' threw an exception of type 'System.NullReferenceException' System.Collections.Generic.IDictionary<string, object> {System.NullReferenceException}
+ Field '((HotChocolate.Execution.Processing.MiddlewareContext)context).Field' threw an exception of type 'System.NullReferenceException' HotChocolate.Types.IObjectField {System.NullReferenceException}
+ FieldSelection '((HotChocolate.Execution.Processing.MiddlewareContext)context).FieldSelection' threw an exception of type 'System.NullReferenceException' HotChocolate.Language.FieldNode {System.NullReferenceException}
HasCleanupTasks false bool
HasErrors false bool
IsResultModified false bool
LocalContextData null System.Collections.Immutable.IImmutableDictionary<string, object>
+ ObjectType '((HotChocolate.Execution.Processing.MiddlewareContext)context).ObjectType' threw an exception of type 'System.NullReferenceException' HotChocolate.Types.IObjectType {System.NullReferenceException}
+ Operation '((HotChocolate.Execution.Processing.MiddlewareContext)context).Operation' threw an exception of type 'System.NullReferenceException' HotChocolate.Execution.Processing.IOperation {System.NullReferenceException}
+ OperationResult {HotChocolate.Execution.Processing.MiddlewareContext.OperationResultBuilderFacade} HotChocolate.Resolvers.IOperationResultBuilder {HotChocolate.Execution.Processing.MiddlewareContext.OperationResultBuilderFacade}
ParentResult null HotChocolate.Execution.Processing.ObjectResult
+ Path '((HotChocolate.Execution.Processing.MiddlewareContext)context).Path' threw an exception of type 'System.NullReferenceException' HotChocolate.Path {System.NullReferenceException}
+ PureResolver '((HotChocolate.Execution.Processing.MiddlewareContext)context).PureResolver' threw an exception of type 'System.NullReferenceException' HotChocolate.Resolvers.PureFieldDelegate {System.NullReferenceException}
+ RequestAborted IsCancellationRequested = false System.Threading.CancellationToken
+ RequestServices '((HotChocolate.Execution.Processing.MiddlewareContext)context).RequestServices' threw an exception of type 'System.NullReferenceException' System.IServiceProvider {System.NullReferenceException}
+ ResolverPipeline '((HotChocolate.Execution.Processing.MiddlewareContext)context).ResolverPipeline' threw an exception of type 'System.NullReferenceException' HotChocolate.Resolvers.FieldDelegate {System.NullReferenceException}
ResponseIndex 0 int
+ ResponseName '((HotChocolate.Execution.Processing.MiddlewareContext)context).ResponseName' threw an exception of type 'System.NullReferenceException' string {System.NullReferenceException}
Result null object
+ Schema '((HotChocolate.Execution.Processing.MiddlewareContext)context).Schema' threw an exception of type 'System.NullReferenceException' HotChocolate.ISchema {System.NullReferenceException}
ScopedContextData null System.Collections.Immutable.IImmutableDictionary<string, object>
Selection null HotChocolate.Execution.Processing.ISelection
Services null System.IServiceProvider
ValueType null HotChocolate.Types.IType
+ Variables '((HotChocolate.Execution.Processing.MiddlewareContext)context).Variables' threw an exception of type 'System.NullReferenceException' HotChocolate.Execution.IVariableValueCollection {System.NullReferenceException}
+ Static members
+ Non-Public members
Additional context
I'm not sure if this will be helpful, but I was able to check the normal values by injecting IHttpContextAccessor.
I believe I have encountered this issue before. The basic problem seems to be that the resolver context is disposed after it produces the stream object (an IAsyncEnumerable<...> in my case) so that by the time MoveNextAsync() is invoked on the stream object to produce items to be streamed the resolver context is cleared out and useless. I had to work around this by capturing all information I need from the resolver context into my stream object.
This is correct, the resolver context should not be used with in results or spawned of. With version 14 we have added two more ways to deal with this, IResolverResultPostProcessor which runs after the resolver pipeline and we streamlined IExecutable which allows to wrap service scopes into a unit that can be spawned of.