Directive on query element is not resolving arguments
See original GitHub issueIs there an existing issue for this?
- I have searched the existing issues
Product
Hot Chocolate
Describe the bug
I created a directive @urlContext(url: String!)
for the Query
element. Added a middleware and was set that for the .Use
on the directive definition. When the middleware is executed the directive is found below the context.Directive
but when executing context.Directive.GetArgument<string>("url")
I always getting null
out.
If instead adding the directive on the field/field definition the middleware and get arguments methods are working as expected.
Workaround that I found is to use this to find the directive argument value
var directive = context.Operation.Definition.Directives.FirstOrDefault(x => x.Name.Value == context.Directive.Name);
var argument = directive?.Arguments.FirstOrDefault(x => x.Name.Value == "url");
var urlString = argument?.Value.Value as string;
if ((argument?.Value.Kind != HotChocolate.Language.SyntaxKind.Variable
|| context.Variables.TryGetVariable(urlString, out urlString))
&& !string.IsNullOrEmpty(urlString)
&& Uri.TryCreate(urlString, UriKind.RelativeOrAbsolute, out var url))
{
}
Steps to reproduce
Schema
directive @UrlContext(
"""
The url for the contextual information.
"""
url: String = "not-set"
) on QUERY | MUTATION | FIELD | OBJECT | FIELD_DEFINITION
type Query {
content: String!
}
Query
query @UrlContext(url: "https://github.com") {
content
}
Directive definition
public class UrlContext
{
public string Url { get; set; }
}
public class UrlContextType : DirectiveType<UrlContext>
{
protected override void Configure(IDirectiveTypeDescriptor<UrlContext> descriptor)
{
descriptor.Argument(x => x.Url)
//.Type<NonNullType<StringType>>()
.Description("The url for the contextual information.")
.DefaultValue("not-set");
descriptor.Location(DirectiveLocation.Query | DirectiveLocation.Mutation | DirectiveLocation.Field | DirectiveLocation.FieldDefinition | DirectiveLocation.Object);
descriptor.Use<UrlContextMiddleware>();
}
}
Directive middleware
public class UrlContextMiddleware
{
private readonly FieldDelegate _next;
public UrlContextMiddleware(
FieldDelegate next)
{
_next = next;
}
// this method must be called InvokeAsync or Invoke
public async ValueTask InvokeAsync(IDirectiveContext context)
{
// Code up here is executed before the following middleware
// and the actual field resolver
var url = context.Directive.GetArgument<string>("url"); // this always return null when directive is on query
// This invokes the next middleware
// or if we are at the last middleware the field resolver
await _next(context);
// Code down here is executed after all later middleware
// and the actual field resolver has finished executing
}
}
Relevant log output
No response
Additional Context?
No response
Version
13.0.0-preview.85
Issue Analytics
- State:
- Created 8 months ago
- Comments:12 (8 by maintainers)
Top Results From Across the Web
Field arguments vs. directives in GraphQL
Directives can be more efficient than field arguments On execution time, a field argument will be accessed when resolving the field, which ...
Read more >Directives - Apollo GraphQL Docs
Directives can take arguments of their own ( reason in this case). ... If true , the decorated field or fragment in an...
Read more >Creating schema directives - Apollo GraphQL Docs
The directive takes one optional argument ( reason ) with a default value ( "No longer supported" ). The directive can decorate any...
Read more >Unit testing Directive with arguments in Angular 2+
The directive is working fine in other components. it accepts a color argument variable defined in the ts file and use it as...
Read more >Argument directive [QUESTION] · Issue #188 · graphql-java ...
I'm new to spring boot and graphql, and I'm trying to write a directive that checks that the argument is within a certain...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I would use headers for thinks that belong into headers. What I would be carefull with is allowing people to put contextual information on selections. The GraphQL query would become very crowded. Also, its not very clear where you have to set them.
If you set them just on the operation level it would be fine.
Thanks, now it was working.
Do you, from the above information, think that it’s better to send this contextual information as http-header information?
the query compilation phase is that the same as implementing an
IHttpRequestInterceptor
or how do I inject my own code inside that?