0

I'm trying to create my own filter for a specific type of data in hotchocolate. I created a class from FilterInputType<MyType> and specified an additional field for filtering in it. For this field, I specified my own handler, which I implemented by inheriting from the QueryableOperationHandlerBase class, and also specified this handler in the convention. But it is not processed in any way and does not even go there, what is the reason for this. I would be grateful if you could provide detailed documentation on this topic or code examples, as hotchocolate has quite scant documentation on this topic.

public class SampleTestFilter : FilterInputType<SampleTest>
{
    protected override void Configure(IFilterInputTypeDescriptor<SampleTest> descriptor)
    {
        base.Configure(descriptor);

        descriptor.Field("testKind")
                  .Type<TestKindFilterType>()
                  .Extend()
                  .OnBeforeCreate(x => x.Handler = new TestKindFilterHandler(new InputParser()));
    }
}

public class TestKindFilterType : InputObjectType
{
    protected override void Configure(IInputObjectTypeDescriptor descriptor)
    {
        descriptor.Field("value").Type<StringType>();
    }
}

public class TestKindFilterHandler : QueryableOperationHandlerBase
{
    public TestKindFilterHandler(InputParser inputParser) : base(inputParser)
    {
    }

    public override bool CanHandle(ITypeCompletionContext context, IFilterInputTypeDefinition typeDefinition, IFilterFieldDefinition fieldDefinition)
    {
        return context is TestKindFilterType;
    }


    public override Expression HandleOperation(QueryableFilterContext context, IFilterOperationField field, IValueNode value, object? parsedValue)
    {
        var entity = Expression.Parameter(typeof(SampleTest), "x1");
        var parameters = Expression.PropertyOrField(entity, nameof(SampleTest.Parameters));
        var entityParameter = Expression.Parameter(typeof(AccountingParameterBase), "x1");
        var wrapperValue = Expression.Call(typeof(EF),
                                           nameof(EF.Property),
                                           new[]
                                           {
                                       typeof(object)
                                           },
                                           entityParameter,
                                           Expression.Constant("_wrappedValue"));
        var propertyName = Expression.Constant("_valueString");
        var propertyValue = Expression.Constant(value.Value.ToString(), typeof(string));
        var charValue = Expression.Call(typeof(EF),
                                        nameof(EF.Property),
                                        new[]
                                        {
                                    propertyValue.Type
                                        },
                                        wrapperValue,
                                        propertyName);
        var comparison = Expression.Equal(charValue, propertyValue);
        var nullValue = Expression.Call(typeof(EF),
                                nameof(EF.Property),
                                new[]
                                {
                                    typeof(object)
                                },
                                wrapperValue,
                                Expression.Constant("_type"));
        var nullExp = Expression.Equal(nullValue, Expression.Constant(null));
        var condition = comparison;
        Expression<Func<AccountingParameterBase, bool>> predicate = Expression.Lambda<Func<AccountingParameterBase, bool>>(condition, entityParameter);
        var anyCall = Expression.Call(typeof(Enumerable),
                                  nameof(Enumerable.Any),
                                  new[]
                                  {
                              typeof(AccountingParameterBase)
                                  },
                                  parameters,
                                  predicate);
        var result = Expression.Lambda<Func<SampleTest, bool>>(anyCall, entity);

        return result;
    }
}

Handler QueryableOperationHandlerBase fails how to make it work. I also tried to make a handler from other base classes of hotchocolate, looked at implementation examples in the source code of hotchocolate.Data. It didn't help.

7
  • create my own filter for a specific type why? This is an overcomplicated way of adding a .Where() to a LINQ query. And even if there's some justification for this, why use reflection instead of writing the Where query? Commented Sep 12 at 8:15
  • it is not processed in any way did you register this anywhere? Or in the correct place? This shows a FilterInputType but TestKindFilterHandler works only with EF Core, or at least a source that uses LINQ. Commented Sep 12 at 8:19
  • This filter is used for nested object properties. class My type{ string id {get;set;} [UseFiltiring("MyFilter")] string IEnumerable<MyNestedType> fields {get;set;} } Commented Sep 12 at 8:22
  • I registered this filter through the convention and the provider handler at hot chocolate Commented Sep 12 at 8:24
  • What you wrote only works on LINQ queries. The expression has to be applied to the LINQ query / DbContext, which happens in the query resolver. Commented Sep 12 at 8:24

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.