HotChocolate 13:Schema First模式下Mutation无法正常工作
问题解决:HotChocolate 13 Schema First下Mutation Relay ID转换失败
问题根源
在Schema First模式下,SDL中定义的ID!类型默认会被映射为C#的string类型,而你在UpdatePostInput中用[ID(nameof(Post))]标记的int Id,框架并没有自动触发Relay ID(Base64编码格式)的解析逻辑——这和Code First模式不同,Code First会通过属性自动生成对应的类型配置;Query操作则是因为框架对Query参数的ID解析做了默认处理。
解决方案
方案一:通过输入类型绑定配置ID解析
创建自定义输入类型描述器,显式指定Id字段的Relay ID类型关联,触发自动解析:
- 定义输入类型配置类:
public class UpdatePostInputType : InputObjectType<UpdatePostInput> { protected override void Configure(IInputObjectTypeDescriptor<UpdatePostInput> descriptor) { descriptor.Field(t => t.Id) .ID(nameof(Post)); // 关联Post类型,让框架自动解析Relay ID } }
- 在GraphQL服务配置中绑定该类型:
builder.Services.AddGraphQLServer() .AddGlobalObjectIdentification() .AddMutationType() .BindRuntimeType<UpdatePostInput, UpdatePostInputType>(); // 绑定输入类型配置
方案二:手动解码Relay ID
如果不想创建额外的类型配置,可以在业务方法中手动解码ID,需先调整UpdatePostInput的Id类型为string:
- 修改
UpdatePostInput定义:
public record UpdatePostInput(string Id, string Title, string Content, List<PostTagInput> Tags);
- 在
UpdatePostAsync方法中注入IIdSerializer解码ID:
[UseDbContext(typeof(ApiContext))] public async Task<UpdatePostPayload> UpdatePostAsync(UpdatePostInput input, [Service] ITopicEventSender eventSender, [Service] IIdSerializer idSerializer, CancellationToken cancellationToken, ApiContext context) { // 解码Relay ID为int类型 var (_, postIdStr) = idSerializer.Deserialize(input.Id); if (!int.TryParse(postIdStr, out var postId)) { // 处理ID解析失败的情况 return new UpdatePostPayload { Errors = new List<ApiError> { new ApiError("Invalid post ID") } }; } // 使用postId进行后续业务操作 ... }
方案三:全局配置输入ID转换器(谨慎使用)
如果多个输入类型都需要处理Relay ID到int的转换,可以配置全局类型转换器,但要注意可能影响其他ID字段的解析:
builder.Services.AddGraphQLServer() .AddGlobalObjectIdentification() .AddMutationType() .AddTypeConverter<string, int>((input, context) => { var idSerializer = context.Services.GetRequiredService<IIdSerializer>(); var (_, id) = idSerializer.Deserialize(input); return int.Parse(id); });
内容的提问来源于stack exchange,提问作者Snoke
相关产品推荐
相关产品推荐

