graphql-dotnet 如何从代码调用查询
graphql-dotnet how to call a query from code
我目前正在尝试从代码中调用 graphql-query 上的字段,而不使用 http 层。在一个测试用例中,我成功地在字段解析器中使用了这个片段。断点命中。
var newContext = new ResolveFieldContext(context);
var query = context.ParentType;
var ticketQueryField = query.GetField("getTickets");
await (Task) ticketQueryField.Resolver.Resolve(context);
所以我认为可以用我真正需要的 fields/arguments 填充复制的 ResolveFieldContext
并这样称呼它。但是手动填充 ResolveFieldContext
非常...复杂。所以也许有更简单的方法来创建上下文。喜欢:
var newContext = new ResolveFieldContext("query test { getTickets(id: 1) { number, title } }");
那真是太棒了,在我的真实场景中,我想通过生成的查询访问的不仅仅是字段。
为什么我要这样使用Graph?我们在 GraphQL-Types 中使用的 Batch-Loader 非常适合我们的需求。
您可以直接使用 DocumentExecutor
来执行没有 http 的 GraphQL 查询,如果您想要特定格式的数据,则提供您自己的 DocumentWriter
。有一个扩展方法 returns JSON,但你可以自己写。
这是用于测试查询的示例测试库 class:
https://github.com/graphql-dotnet/graphql-dotnet/blob/master/src/GraphQL.Tests/BasicQueryTestBase.cs
这是一个控制台示例 returns JSON,不使用 http。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Authorization;
using GraphQL.SystemTextJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.Extensions.DependencyInjection;
namespace BasicSample
{
internal class Program
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "main")]
private static async Task Main()
{
using var serviceProvider = new ServiceCollection()
.AddSingleton<IAuthorizationEvaluator, AuthorizationEvaluator>()
.AddTransient<IValidationRule, AuthorizationValidationRule>()
.AddTransient(s =>
{
var authSettings = new AuthorizationSettings();
authSettings.AddPolicy("AdminPolicy", p => p.RequireClaim("role", "Admin"));
return authSettings;
})
.BuildServiceProvider();
string definitions = @"
type User {
id: ID
name: String
}
type Query {
viewer: User
users: [User]
}
";
var schema = Schema.For(definitions, builder => builder.Types.Include<Query>());
// remove claims to see the failure
var authorizedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("role", "Admin") }));
string json = await schema.ExecuteAsync(_ =>
{
_.Query = "{ viewer { id name } }";
_.ValidationRules = serviceProvider
.GetServices<IValidationRule>()
.Concat(DocumentValidator.CoreRules);
_.RequestServices = serviceProvider;
_.UserContext = new GraphQLUserContext { User = authorizedUser };
});
Console.WriteLine(json);
}
}
/// <summary>
/// Custom context class that implements <see cref="IProvideClaimsPrincipal"/>.
/// </summary>
public class GraphQLUserContext : Dictionary<string, object>, IProvideClaimsPrincipal
{
/// <inheritdoc />
public ClaimsPrincipal User { get; set; }
}
/// <summary>
/// CLR type to map to the 'Query' graph type.
/// </summary>
public class Query
{
/// <summary>
/// Resolver for 'Query.viewer' field.
/// </summary>
[GraphQLAuthorize("AdminPolicy")]
public User Viewer() => new User { Id = Guid.NewGuid().ToString(), Name = "Quinn" };
/// <summary>
/// Resolver for 'Query.users' field.
/// </summary>
public List<User> Users() => new List<User> { new User { Id = Guid.NewGuid().ToString(), Name = "Quinn" } };
}
/// <summary>
/// CLR type to map to the 'User' graph type.
/// </summary>
public class User
{
/// <summary>
/// Resolver for 'User.id' field. Just a simple property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Resolver for 'User.name' field. Just a simple property.
/// </summary>
public string Name { get; set; }
}
}
我目前正在尝试从代码中调用 graphql-query 上的字段,而不使用 http 层。在一个测试用例中,我成功地在字段解析器中使用了这个片段。断点命中。
var newContext = new ResolveFieldContext(context);
var query = context.ParentType;
var ticketQueryField = query.GetField("getTickets");
await (Task) ticketQueryField.Resolver.Resolve(context);
所以我认为可以用我真正需要的 fields/arguments 填充复制的 ResolveFieldContext
并这样称呼它。但是手动填充 ResolveFieldContext
非常...复杂。所以也许有更简单的方法来创建上下文。喜欢:
var newContext = new ResolveFieldContext("query test { getTickets(id: 1) { number, title } }");
那真是太棒了,在我的真实场景中,我想通过生成的查询访问的不仅仅是字段。
为什么我要这样使用Graph?我们在 GraphQL-Types 中使用的 Batch-Loader 非常适合我们的需求。
您可以直接使用 DocumentExecutor
来执行没有 http 的 GraphQL 查询,如果您想要特定格式的数据,则提供您自己的 DocumentWriter
。有一个扩展方法 returns JSON,但你可以自己写。
这是用于测试查询的示例测试库 class: https://github.com/graphql-dotnet/graphql-dotnet/blob/master/src/GraphQL.Tests/BasicQueryTestBase.cs
这是一个控制台示例 returns JSON,不使用 http。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Authorization;
using GraphQL.SystemTextJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.Extensions.DependencyInjection;
namespace BasicSample
{
internal class Program
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "main")]
private static async Task Main()
{
using var serviceProvider = new ServiceCollection()
.AddSingleton<IAuthorizationEvaluator, AuthorizationEvaluator>()
.AddTransient<IValidationRule, AuthorizationValidationRule>()
.AddTransient(s =>
{
var authSettings = new AuthorizationSettings();
authSettings.AddPolicy("AdminPolicy", p => p.RequireClaim("role", "Admin"));
return authSettings;
})
.BuildServiceProvider();
string definitions = @"
type User {
id: ID
name: String
}
type Query {
viewer: User
users: [User]
}
";
var schema = Schema.For(definitions, builder => builder.Types.Include<Query>());
// remove claims to see the failure
var authorizedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("role", "Admin") }));
string json = await schema.ExecuteAsync(_ =>
{
_.Query = "{ viewer { id name } }";
_.ValidationRules = serviceProvider
.GetServices<IValidationRule>()
.Concat(DocumentValidator.CoreRules);
_.RequestServices = serviceProvider;
_.UserContext = new GraphQLUserContext { User = authorizedUser };
});
Console.WriteLine(json);
}
}
/// <summary>
/// Custom context class that implements <see cref="IProvideClaimsPrincipal"/>.
/// </summary>
public class GraphQLUserContext : Dictionary<string, object>, IProvideClaimsPrincipal
{
/// <inheritdoc />
public ClaimsPrincipal User { get; set; }
}
/// <summary>
/// CLR type to map to the 'Query' graph type.
/// </summary>
public class Query
{
/// <summary>
/// Resolver for 'Query.viewer' field.
/// </summary>
[GraphQLAuthorize("AdminPolicy")]
public User Viewer() => new User { Id = Guid.NewGuid().ToString(), Name = "Quinn" };
/// <summary>
/// Resolver for 'Query.users' field.
/// </summary>
public List<User> Users() => new List<User> { new User { Id = Guid.NewGuid().ToString(), Name = "Quinn" } };
}
/// <summary>
/// CLR type to map to the 'User' graph type.
/// </summary>
public class User
{
/// <summary>
/// Resolver for 'User.id' field. Just a simple property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Resolver for 'User.name' field. Just a simple property.
/// </summary>
public string Name { get; set; }
}
}