diff --git a/src/HotChocolate/Data/src/Data/Projections/Convention/ProjectionInterceptorCombinator.cs b/src/HotChocolate/Data/src/Data/Projections/Convention/ProjectionInterceptorCombinator.cs new file mode 100644 index 00000000000..849ad0df54d --- /dev/null +++ b/src/HotChocolate/Data/src/Data/Projections/Convention/ProjectionInterceptorCombinator.cs @@ -0,0 +1,53 @@ +using HotChocolate.Execution.Processing; + +namespace HotChocolate.Data.Projections.Handlers +{ + /// + /// This wrapper is used to combined two interceptors and create a chain + /// + internal class ProjectionInterceptorCombinator + : IProjectionFieldInterceptor + where T : IProjectionVisitorContext + { + private readonly IProjectionFieldInterceptor _current; + private readonly IProjectionFieldInterceptor _next; + + public ProjectionInterceptorCombinator( + IProjectionFieldInterceptor current, + IProjectionFieldInterceptor next) + { + _current = current; + _next = next; + } + + public bool CanHandle(ISelection selection) => true; + + public void BeforeProjection( + T context, + ISelection selection) + { + if (_current is IProjectionFieldInterceptor currentHandler) + { + currentHandler.BeforeProjection(context, selection); + } + + if (_next is IProjectionFieldInterceptor nextHandler) + { + nextHandler.BeforeProjection(context, selection); + } + } + + public void AfterProjection(T context, ISelection selection) + { + if (_next is IProjectionFieldInterceptor nextHandler) + { + nextHandler.AfterProjection(context, selection); + } + + if (_current is IProjectionFieldInterceptor currentHandler) + { + currentHandler.AfterProjection(context, selection); + } + } + } +} diff --git a/src/HotChocolate/Data/src/Data/Projections/Expressions/Handlers/ProjectionFieldWrapper.cs b/src/HotChocolate/Data/src/Data/Projections/Expressions/Handlers/ProjectionFieldWrapper.cs index 391242bcaac..c3237459540 100644 --- a/src/HotChocolate/Data/src/Data/Projections/Expressions/Handlers/ProjectionFieldWrapper.cs +++ b/src/HotChocolate/Data/src/Data/Projections/Expressions/Handlers/ProjectionFieldWrapper.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using HotChocolate.Data.Projections.Handlers; using HotChocolate.Execution.Processing; namespace HotChocolate.Data.Projections.Expressions.Handlers @@ -22,7 +23,7 @@ public bool CanHandle(ISelection selection) => _handler.CanHandle(selection); public IProjectionFieldHandler Wrap(IProjectionFieldInterceptor interceptor) => - _handler.Wrap(interceptor); + _handler.Wrap(new ProjectionInterceptorCombinator(_interceptor, interceptor)); public T OnBeforeEnter(T context, ISelection selection) => _handler.OnBeforeEnter(context, selection); diff --git a/src/HotChocolate/Data/src/Data/Projections/Expressions/Interceptor/QueryableFilterInterceptor.cs b/src/HotChocolate/Data/src/Data/Projections/Expressions/Interceptor/QueryableFilterInterceptor.cs index a6a4fb359af..2556e90d98e 100644 --- a/src/HotChocolate/Data/src/Data/Projections/Expressions/Interceptor/QueryableFilterInterceptor.cs +++ b/src/HotChocolate/Data/src/Data/Projections/Expressions/Interceptor/QueryableFilterInterceptor.cs @@ -43,7 +43,7 @@ argVisitor is VisitFilterArgument argumentVisitor && out IReadOnlyDictionary? coercedArgs) && coercedArgs.TryGetValue(argumentName, out var argumentValue) && argumentValue.Argument.Type is IFilterInputType filterInputType && - argumentValue.ValueLiteral is {} valueNode && + argumentValue.ValueLiteral is { } valueNode && valueNode is not NullValueNode) { QueryableFilterContext filterContext = diff --git a/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionFilterTests.cs b/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionFilterTests.cs index f6826cbc70c..9694391b790 100644 --- a/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionFilterTests.cs +++ b/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionFilterTests.cs @@ -405,6 +405,7 @@ public class FooNullable public bool? BarBool { get; set; } [UseFiltering] + [UseSorting] public List? ObjectArray { get; set; } public BarNullableDeep? NestedObject { get; set; } diff --git a/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionSortingTests.cs b/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionSortingTests.cs index 51d4aad0604..f3eedefd49c 100644 --- a/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionSortingTests.cs +++ b/src/HotChocolate/Data/test/Data.Projections.SqlServer.Tests/QueryableProjectionSortingTests.cs @@ -324,6 +324,7 @@ public class Foo public bool BarBool { get; set; } + [UseFiltering] [UseSorting] public List ObjectArray { get; set; }