LuccaSA / RestDrivenDomain

8 stars 1 forks source link

filter on nested collection doesn't work #328

Closed srabere closed 5 years ago

srabere commented 5 years ago

When I try to filter on nested collection property, I get an error. See the stack below. The error appears in Rdd.Infra.Helpers.ExpressionExtension at line 25. Take an example with this API call api/entities?nestedCollection.property=1. The generated expression should be something like entities.Where(e => e.NestedCollection.Any(nc => nc.Property == 1)). But the actual generated expression seems to be ntities.Where(e => e.NestedCollection.Select(nc => nc.Property) == 1), which can't work.

Stack trace : ArgumentException: Object of type 'System.Int32' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[System.Int32]'. System.RuntimeType.TryChangeType(object value, Binder binder, CultureInfo culture, bool needsSpecialCast) System.Reflection.MethodBase.CheckArguments(object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) System.Reflection.RuntimeMethodInfo.Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) Rdd.Infra.Helpers.ExpressionExtension.ExtractTypedExpression(object value, Type type) in ExpressionExtension.cs Rdd.Infra.Helpers.WebFilterConverter<TEntity>.Contains(Expression leftExpression, IList values) in WebFilterConverter.cs Rdd.Infra.Helpers.WebFilterConverter<TEntity>.BuildLambda<TValue>(Func<Expression, TValue, Expression> builder, IExpression field, TValue value) in WebFilterConverter.cs Rdd.Infra.Helpers.WebFilterConverter<TEntity>.Equals(IExpression field, IList values) in WebFilterConverter.cs System.Linq.Enumerable+WhereSelectEnumerableIterator<TSource, TResult>.ToArray() System.Linq.Enumerable.ToArray<TSource>(IEnumerable<TSource> source) NExtends.Expressions.BooleanExpression.AndAggregation<TEntity>(IEnumerable<Expression<Func<TEntity, bool>>> filters) Rdd.Web.Querying.FilterParser.Parse<TEntity>(HttpRequest request, ActionDescriptor action, IWebFilterConverter<TEntity> webFilterConverter) in FilterParser.cs Rdd.Web.Querying.QueryParser<TEntity>.Parse(HttpRequest request, ActionDescriptor action, bool isCollectionCall) in QueryParser.cs Rdd.Web.Controllers.ReadOnlyWebController<TAppController, TEntity, TKey>.GetAsync() Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments) System.Threading.Tasks.ValueTask<TResult>.get_Result() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) Timmi.Web.Authentication.SetupCurrentPrincipalMiddleware.Invoke(HttpContext httpContext) in SetupCurrentPrincipalMiddleware.cs + await _next.Invoke(httpContext); Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context) Lucca.Core.AspNetCore.Tenancy.TenantContextResolutionMiddleware<TTenant>.Invoke(HttpContext context, TenantContext<TTenant> tenantContext, TenantInfos infoContext) in TenantContextResolutionMiddleware.cs Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Poltuu commented 5 years ago

this functionality seems to have been dropped, but I don't believe it should have been. I'll fix it

Poltuu commented 5 years ago

https://github.com/LuccaSA/RestDrivenDomain/pull/329

srabere commented 5 years ago

Thanks, so fast !