First, the ID scalar type is part of GraphQL standard, and defined as:
In GraphQL the ID scalar type represents a unique identifier, often
used to refetch an object or as the key for a cache. The ID type is
serialized in the same way as a String; however, defining it as an ID
signifies that it is not intended to be human‐readable.
Relay is a GraphQL client JavaScript framework for React applications. Apollo GraphQL is another alternative.
HotChocolate has a few helpers to enable "Relay-style GraphQL API". These helpers will convert the id-field to a base64-encoded hash, serialized as a string. This is a good thing because:
- it helps with caching, all entities has a unique id
- hide actual id from users (?)
Even though you enable "Relay support" in HotChocolate, you don't have to use Relay, you can still use any GraphQL client (Apollo client is my favourite)
Now, if you just want to use the GraphQL ID scalar type, you can try this as I suggested first:
First remove ID-attribute from query:
[ExtendObjectType(Name = GraphqlQueryNames.Query)]
public class EmployeeQuery
{
public async Task<Employee> GetEmployeeByIdAsync(
int id,
[Service] IEmployeeRepository employeeRepository,
CancellationToken token)
{
return await employeeRepository.GetEmployeeByIdAsync(id, token);
}
}
then specify ID scalar type like this:
public class EmployeeType : ObjectType<Employee>
{
protected override void Configure(IObjectTypeDescriptor<Employee> descriptor)
{
descriptor.Field(r => r.Id).Type<IdType>;
}
}
But if you want to enable "Relay support" in HotChocolate, follow Arsync's answer (I changed this to HotChocolate v11 which has slightly different syntax):
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGraphQLServer().EnableRelaySupport();
}
}
Update for Hot Chocolate v12: It's now possible to enable global identification, but without other relay related stuff:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGraphQLServer().AddGlobalObjectIdentification();
}
}
Then in your type definition:
public class EmployeeType : ObjectType<Employee>
{
protected override void Configure(IObjectTypeDescriptor<Employee> descriptor)
{
// Relay ID support. Retailer.Id will be a hash. the real id / int is available below when passed to DataLoader
descriptor
.ImplementsNode()
.IdField(c => c.Id)
.ResolveNode(((context, id) => context.DataLoader<EmployeeByIdDataLoader>().LoadAsync(id, context.RequestAborted)));
}
}
Or even simpler with v12:
public class EmployeeType : ObjectType<Employee>
{
protected override void Configure(IObjectTypeDescriptor<Employee> descriptor)
{
descriptor
.Field(f => f.Id).ID(nameof(Employee));
}
}
If you try to query for employees now you'll see that id is not an integer, but a hash. Something like "TGFuZ3VhZ2UKaTE=". This hash is generated by HotChocolate, see IdSerializer source. If you try to base64 decode this string:
$ echo "TGFuZ3VhZ2UKaTE=" | base64 -d
Employee
i1
The errormessage you received "The ID 1 has invalid format", is because it now expects a hashed string, and not an integer.
This query should work:
query getEmployeeById {
employeeById(id: "TGFuZ3VhZ2UKaTE=") {
familyName
}
}