Search code examples
.net-coregraphqlhotchocolate

Hot Chocolate: filtering with a char field


How can I set up Hot Chocolate filtering to work when a class has a char field?

I have a class with a Status field of type char. Strangely, it seems that Hot Chocolate does not work with char fields. To get it to even generate a schema I had to configure AddGraphQLServer() like this:

builder.BindRuntimeType<char, StringType>()

and then to get queries to work I had to do this:

builder.AddTypeConverter<char, string>(_ => _.ToString())

(I presume I will need AddTypeConverter<string, char> for mutations.)

But filtering does not work. If I add [UseFiltering] to a resolver, I can no longer even generate a schema. The error I get is

The type of the member Status of the declaring type Offer is unknown

What is the simplest way to get filtering to work here? I have read some slightly out-of-date inforamtion about IFilterConvention but haven't been able to get anything working. I hope this very simple thing (which really should work out of the box) will require only a little bit more code.


Solution

  • It's all a bit awkward, since char is not a first-class GraphQL type. We added converters to convert between char and string, and added a custom filter convention so we could filter by char.

    public void ConfigureServices(IServiceCollection services)
    {
        services
            // Add our custom conventions for filtering
            .AddConvention<IFilterConvention, CustomFilterConvention>()
            // Add support for char (treat as string)
            .BindRuntimeType<char, StringType>()
            .AddTypeConverter<char, string>(_ => _.ToString())
            .AddTypeConverter<string, char>(_ => _[0])
            // Add support for char? (treat as string)
            .BindRuntimeType<char?, StringType>()
            .AddTypeConverter<char?, string>(_ => _?.ToString() ?? "")
            .AddTypeConverter<string, char?>(_ => _[0])
            // ...etc
    }
    
    public class CustomFilterConvention : FilterConvention
    {
        protected override void Configure(IFilterConventionDescriptor descriptor)
        {
            base.Configure(descriptor);
    
            descriptor.BindRuntimeType<char, ComparableOperationFilterInputType<char>>();
            descriptor.BindRuntimeType<char?, ComparableOperationFilterInputType<char?>>();
            descriptor.AddDefaults();
            descriptor.Provider(new QueryableFilterProvider(_ => _.AddDefaultFieldHandlers()));
        }
    }
    

    I think a better approach might be to just change our entity class to use string instead of char. Might try that later.