GraphQL Server with Hot Chocolate
使用 Hot Chocolate v13.81 實作 GraphQL Server。
引言
在 .NET Core 有多種實作 GraphQL 方案。本人選取 ChilliCream GraphQL Platform 的 Hot Chocolate v13 實作 Server 端;Strawberry Shake v13 實作 Client 端。
實作前需知
GraphQL 發展過程已過數個迭代。就 Hot Chocolate 來說至少有主要三種世代的開發模式:Schema-first 、Code-first、Annotation-based。我們只採用最新的開發模式:Annotation-based。
開發教學部份官網已有最新的版本教學說明。強烈建議以官網的說明為主,因為其他網頁的說明太多是舊的模式,就本人經驗上與 Annotation-based 模式不相容。
開發環境
平台: .NET6
IDE: Visual Studio 2022
框架: Blazor Swagger API
Hot Chocolate 官方教學
官方教學已從入門開始,就不再手把手教學。
Hot Chocolate 關鍵程式碼紀錄
官方教學已從入門開始,就不再手把手教學。以下只紀錄重要的關鍵的部份。
Program.cs -註冊 GraphQLServer
使用 Annotation-based 模式開發需要寫的碼變得很少。
GraphQL Schema 只有一套,在註冊時,AddQueryType、AddMutationType、AddSubscriptionType 各別只能註開一次,為各別的進入點。
[...略...]
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
//## for GrqphQL
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>() // GrqphQL query.
.AddType<ProductQuery>() // ExtendObjectType of Query
.AddType<BookQuery>() // ExtendObjectType of Query
.AddMutationType<Mutation>() // for GrqphQL mutation.
.AddSubscriptionType<Subscription>() // for GrqphQL subscriptions.
.AddInMemorySubscriptions();
[...略...]
var app = builder.Build();
[...略...]
app.MapControllers();
//## for GrqphQL
app.MapGraphQL();
app.UseWebSockets(); // for GrqphQL subscriptions.
app.Run();
GraphQL - Query 主類別
若該 GraphQL query 的函式量不大其實可以全部集中實作,相信實務上這情境不多,大多情況一定需要分猜偶合,這技巧在此稱作 ExtendObjectType
。
/// GrqphQL query root
/// 若 query 的函式量不大其實可以全部集中在此,相信實務上這情現不多。
public class Query
{
public string Hello(string name = "World") => $"Hello, {name}";
}
ExtendObjectType of Query
當然實務上 Query 的量一定很多,這時用ExtendObjectType
來擴充。若 Mutation 、Subscription 的量很多也是依樣擴充。
[ExtendObjectType(nameof(Query))] //※ ExtendObjectType of Query
public class ProductQuery
{
readonly ProductService _bizSvc;
public ProductQuery([Service]IServiceProvider provider)
{
_bizSvc = provider.GetRequiredService<ProductService>();
}
public Product[] GetProductList() => _bizSvc.QueryProducts().ToArray();
}
GraphQL Schema 範例
若成功的話預設 graphql 網址是:/graphql
。
透過 GraphQL 標註, Hot Chocolate
將自動生成相應的 GraphQL Schema。

Mutation 實作注意事項
mutation 的實作本以為會很麻煩,Hot Chocolate 已整理的非常簡易就能完成。DI injection
大量且全面性的採用。比較麻煩的是命名規範:
輸入:xxxInput
輸出:xxxPayload
using HotChocolate.Subscriptions;
public record ProductAddedPayload(bool IsSuccess, Product NewProduct);
public record ProductInput(string Name, int Quantity);
public class Mutation
{
public async Task<ProductAddedPayload> AddProdcut(ProductInput input,
[Service] IServiceProvider provider, // DI injection
[Service] ITopicEventSender eventSender) // DI injection, 用於subscription。
{
var bizSvc = provider.GetRequiredService<ProductService>(); // DI injection
var product = bizSvc.AddProduct(new Product(0, input.Name, input.Quantity));
var result = new ProductAddedPayload(true, product);
await eventSender.SendAsync(nameof(AddProdcut), result);
// for subscription, 一般並不需要。
// mutation 通告:通告某 client 已有異動了。
return result;
}
}
Subscrition 實作注意事項
注意:GraphQL subscrition 的通訊協定是 WebSocket 記得要打開。
GraphQL subscrition 應用情境主要有二種:
一、mutation 通告。
二、server side streaming。用於即時訊息廣播或 Message Queue、Message Bus 訊息串流等。
using HotChocolate.Subscriptions;
public record TimerTick(string Tick);
public class Subscription
{
#region Server side streaming sample
/// <summary>
/// for: Server side streaming
/// </summary>
public async IAsyncEnumerable<TimerTick> OnTimerTickStream([Service] ITopicEventReceiver eventReceiver)
{
do
{
yield return new TimerTick(Tick: DateTime.Now.ToString("HH:mm:ss.fff"));
await Task.Delay(1000);
}
while (true);
}
/// <summary>
/// Server side streaming
/// subscription 的 in type 與 out type 可以不一樣,此範例太簡單才會一樣。
/// </summary>
[Subscribe(With = nameof(OnTimerTickStream))] //------ 關鍵點
public TimerTick OnTimerTick([EventMessage] TimerTick timerTick)
=> timerTick;
#endregion
/// <summary>
/// Subscribe mutation evnet sample
/// mutation 通告:通告某 client 已有異動了。
/// subscription 的 in type 與 out type 可以不一樣,此範例太簡單才會一樣。
/// </summary>
[Subscribe]
[Topic(nameof(Mutation.AddProdcut))]
public ProductAddedPayload OnProductAdded([EventMessage] ProductAddedPayload message)
=> message;
}
開發測試工具 - Banana Cake Pop
Hot Chocolate 的開發測試工具叫作 Banana Cake Pop。如何使用請看教學影片吧。
完整程式碼
(EOF)
Last updated