ChilliCream / graphql-workshop

Getting started with GraphQL on ASP.NET Core and Hot Chocolate - Workshop
465 stars 199 forks source link

Id field being returned as base64 encoded string instead of Guid #105

Closed mohammad-al-mahamid closed 1 month ago

mohammad-al-mahamid commented 1 year ago

The ID is stored as a Guid in my database, but when queried through GraphQL, it is returned as a base64 encoded string. i am facing this problem after enabling relay policy and implementing the reolver to improve data fetch. Is there a way to configure a custom serializer or scalar type for Guid values in the schema?

michaelstaib commented 1 year ago

That is what the relay spec is about :) ID values are encoded into base64 to allow for global unique identifiers.

mohammad-al-mahamid commented 1 year ago

@michaelstaib as an example the getSpeakers returns the ids as a base64 encoded string, when I try to find another speaker with a specific id I get the error "errors": [ { "message": "The specified argument value does not match the argument type.", "locations": [ { "line": 9, "column": 21 } ], "path": [ "speakerById" ], "extensions": { "argument": "id", "argumentValue": "\"U3BlYWtlcgppMQ== \"", "locationType": "Int!", "specifiedBy": "http://spec.graphql.org/October2021/#sec-Values-of-Correct-Type" } } ] }

I have solved this problem by adding "[ID]" to the queries:

public Task<Speaker> GetSpeakerByIdAsync([ID(nameof(Speaker))] int id, SpeakerByIdDataLoader speakerByIdDataLoader, CancellationToken cancellationToken) => speakerByIdDataLoader.LoadAsync(id, cancellationToken);

but I also face this problem when I try to add a new session, here the ids would not be accepted in the base64 encoding, The error: { "errors": [ { "message": "Int cannot parse the given literal of typeStringValueNode.", "path": [ "input", "speakerIds", 0 ], "extensions": { "field": "AddSessionInput.speakerIds", "fieldType": "Int" } } ] }
how to solve this problem? and is there a way to avoid the base64-encoding?

esausilva commented 1 year ago

You probably already resolved this, but for those having this same issue. When writing the *Input records, do not use parameters, use properties like so

public record AddSessionInput
{
    public string Title { get; set; }
    public string? Abstract { get; set; }
    [ID(nameof(Speaker))] public IReadOnlyList<int> SpeakerIds { get; set; }   
}

I do not know the reason, but by using parameters the global identifiers (ID) will still be ints. By rewriting the records to have properties, the global identifiers (ID) will take the base64 id encodings.

esausilva commented 1 year ago

I created a blog post with all the fixes/upgrades to work with the latest Hot Chocolate and .NET 7 and minimal APIs https://esausilva.com/2023/04/12/solved-graphql-hot-chocolate-workshop-issues-updated/

glen-84 commented 1 month ago

@esausilva

You can also use [property: ID<Speaker>] to target the property, for example:

public sealed record AddSessionInput(
    string Title,
    string? Abstract,
    [property: ID<Speaker>] IReadOnlyList<int> SpeakerIds);
glen-84 commented 1 month ago

I'm closing this issue as outdated, as we have an updated workshop on the main branch, for Hot Chocolate 14.