从 .NET Core 应用程序同时提供 REST 和 GraphQL API
Posted
技术标签:
【中文标题】从 .NET Core 应用程序同时提供 REST 和 GraphQL API【英文标题】:Serve both REST and GraphQL APIs from .NET Core application 【发布时间】:2020-09-28 00:35:21 【问题描述】:我有一个已经在为客户服务的 .NET Core REST API 服务器。
我能否通过添加 HotChocolate 库并定义查询来配置 API 服务器以支持 GraphQL?是否可以从我的 .NET Core 服务器同时提供 GraphQL 和 REST API?
【问题讨论】:
【参考方案1】:是的,支持 REST API(控制器)和 GraphQL 完全没问题。
如果您不考虑库,处理 GraphQL 请求仅意味着处理传入的 POST 到 /graphql
。
如果需要,您可以编写处理这些 POST 的典型 ASP.NET Core 控制器。像 Hot Chocolate 这样的框架提供了像 .UseGraphQl()
这样的中间件,这使得配置更加方便,但从概念上讲,您可以将 .UseGraphQl()
视为添加一个仅处理 /graphql
路由的控制器。您的所有其他控制器将继续正常工作!
【讨论】:
【参考方案2】:有一种方法可以让您使用 hotchocolate 和模式拼接自动同时启动和运行两个 API。
基本上,我遵循了 Ian webbington 提供的这个教程。 https://ian.bebbs.co.uk/posts/LessReSTMoreHotChocolate
Ian 使用其 API 中的 swagger 模式来创建一个 graphql 模式,如果我们考虑一下,这可以节省我们的时间。它很容易实现,但是您仍然需要编写代码来公开 graphql 端点。
这是我实现的,将我的所有 graphql 和其余 API 连接到一个 API 网关中。我正在分享我的自定义实现以在 hotchocolate (Graphql) 下运行 swagger 模式 (REST):
using System;
using HotChocolate;
using HotChocolate.AspNetCore;
using HotChocolate.AspNetCore.Playground;
using HotChocolate.AspNetCore.Voyager;
using HotChocolate.AspNetCore.Subscriptions;
using HotChocolate.Stitching;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using SmartGateway.Api.Filters;
using SmartGateway.Api.RestServices.SmartConfig;
namespace SmartGateway.Api.Extensions
public static class GraphQlExtensions
public static IServiceCollection AddGraphQlApi(this IServiceCollection services)
services.AddHttpClient("smartauth", (sp, client) =>
sp.SetUpContext(client); //GRAPHQL API
client.BaseAddress = new Uri(AppSettings.SmartServices.SmartAuth.Endpoint);
);
services.AddHttpClient("smartlog", (sp, client) =>
sp.SetUpContext(client); //GRAPHQL API
client.BaseAddress = new Uri(AppSettings.SmartServices.SmartLog.Endpoint);
);
services.AddHttpClient("smartway", (sp, client) =>
sp.SetUpContext(client); //GRAPHQL API
client.BaseAddress = new Uri(AppSettings.SmartServices.SmartWay.Endpoint);
);
services.AddHttpClient<ISmartConfigSession, SmartConfigSession>((sp, client) =>
sp.SetUpContext(client); //REST API
client.BaseAddress = new Uri(AppSettings.SmartServices.SmartConfig.Endpoint);
);
services.AddDataLoaderRegistry();
services.AddGraphQLSubscriptions();
services.AddStitchedSchema(builder => builder
.AddSchemaFromHttp("smartauth")
.AddSchemaFromHttp("smartlog")
.AddSchemaFromHttp("smartway")
.AddSchema(new NameString("smartconfig"), SmartConfigSchema.Build())
.AddSchemaConfiguration(c =>
c.RegisterExtendedScalarTypes();
));
services.AddErrorFilter<GraphQLErrorFilter>();
return services;
public static IApplicationBuilder UseGraphQlApi(this IApplicationBuilder app)
app.UseWebSockets();
app.UseGraphQL("/graphql");
app.UsePlayground(new PlaygroundOptions
Path = "/ui/playground",
QueryPath = "/graphql"
);
app.UseVoyager(new PathString("/graphql"), new PathString("/ui/voyager"));
return app;
设置 HttpContext 扩展:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace SmartGateway.Api.Extensions
public static class HttpContextExtensions
public static void SetUpContext(this IServiceProvider servicesProvider, HttpClient httpClient)
HttpContext context = servicesProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
if (context?.Request?.Headers?.ContainsKey("Authorization") ?? false)
httpClient.DefaultRequestHeaders.Authorization =
AuthenticationHeaderValue.Parse(context.Request.Headers["Authorization"].ToString());
您需要它来处理 HTTPClient 并将其传递给您的 swagger Sdk。
using System.Net.Http;
namespace SmartGateway.Api.RestServices.SmartConfig
public interface ISmartConfigSession
HttpClient GetHttpClient();
public class SmartConfigSession : ISmartConfigSession
private readonly HttpClient _httpClient;
public SmartConfigSession(HttpClient httpClient)
_httpClient = httpClient;
public HttpClient GetHttpClient()
return _httpClient;
这是我的 graphql 架构:
namespace SmartGateway.Api.RestServices.SmartConfig
public static class SmartConfigSchema
public static ISchema Build()
return SchemaBuilder.New()
.AddQueryType<SmartConfigQueries>()
.AddMutationType<SmartConfigMutations>()
.ModifyOptions(o => o.RemoveUnreachableTypes = true)
.Create();
public class SmartConfigMutations
private readonly ISmartConfigClient _client;
public SmartConfigMutations(ISmartConfigSession session)
_client = new SmartConfigClient(AppSettings.SmartServices.SmartConfig.Endpoint, session.GetHttpClient());
public UserConfigMutations UserConfig => new UserConfigMutations(_client);
最后,这是您发布端点的方式:
using System.Threading.Tasks;
using SmartConfig.Sdk;
namespace SmartGateway.Api.RestServices.SmartConfig.UserConfigOps
public class UserConfigMutations
private readonly ISmartConfigClient _client;
public UserConfigMutations(ISmartConfigClient session)
_client = session;
public async Task<UserConfig> CreateUserConfig(CreateUserConfigCommand createUserConfigInput)
var result = await _client.CreateUserConfigAsync(createUserConfigInput);
return result.Response;
public async Task<UserConfig> UpdateUserConfig(UpdateUserConfigCommand updateUserConfigInput)
var result = await _client.UpdateUserConfigAsync(updateUserConfigInput);
return result.Response;
更多关于热巧克力和模式拼接的文档在这里: https://hotchocolate.io/docs/stitching
【讨论】:
以上是关于从 .NET Core 应用程序同时提供 REST 和 GraphQL API的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 6框架揭秘实例演示[30]:利用路由开发REST API
ASP.NET Core 项目的 Visual Studio 中的“REST API 客户端”选项?
CORS 错误:LinkedIn 身份验证; .NET Core 5 REST API