ChilliCream / ChilliCream/graphql-platform
Add filtering convention runtime type binding support for open generic types
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 5.8k
- Forks
- 810
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 98
Description
Product
Hot Chocolate
Is your feature request related to a problem?
The BindRuntimeType method on the IFilterConventionDescriptor does not currently work for open generic types. This means that every generic type definition has to be registered separately. Since the filter convention is configured earlier than all schema types are discovered, automatic registration is also not possible via interceptors or other means.
In practical terms, this means that using custom scalars for generic types in combination with filtering for these custom scalars is not possible and leads to incorrect filter inputs being generated, which also cannot be removed or ignored automatically.
Example
builder.Services.AddGraphQLServer()
// ...
.AddFiltering(f =>
{
f.BindRuntimeType(typeof(Id<>), typeof(IdFilterType<>)); // IdFilterType<T> implements ComparableOperationFilterInputType<T>
}
)
This binding is ignored entirely during runtime. Instead of a comparable filter input type, a default object comparison input type is added.
The only way to make it work is to register all types manually:
builder.Services.AddGraphQLServer()
// ...
.AddFiltering(f =>
{
f.BindRuntimeType(typeof(Id<MyEntity>), typeof(IdFilterType<MyEntity>));
f.BindRuntimeType(typeof(Id<OtherEntity>), typeof(IdFilterType<OtherEntity>));
// ... and so on
}
)
This is extremely non-ergonomic and defeats the entire purpose of generic types in C#.
This problem is made much worse by the fact that filtering completely ignores the bindings of custom scalars. Even if a type uses a custom scalar which is a StringValueNode (ScalarType<Id, StringValueNode> for example), filtering still treats it like an object, not a string. This is documented in the HotChocolate documentation, but that shortcoming makes the issue with generic types even worse.
The solution you'd like
The issue could be solved if any of the following fixes are made to the runtime type binding for filtering:
- Allow binding open generic types and/or interfaces which are then correctly resolved at runtime to register the appropriate input objects.
- Use the custom scalars already registered in the schema without separately registering them with the filtering convention.
- Allow binding custom scalars to filter types directly, rather than having to register the underlying runtime type of the custom scalar, and use the actual schema type of the scalar for filtering, e.g. if the custom scalar is a StringValueNode, treat the value as a string for filtering too.
Ideally, all three should be implemented, but any one of the three would fix this particular issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at IFilterConventionDescriptor.BindRuntimeType and reproduce the open-generic example with Id<> and IdFilterType<>. Compare the generated filter input with the expected comparable input, including the custom scalar case. Done means open generic bindings or registered custom scalars produce the appropriate filtering input without manual per-type registrations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100