private Expression GetPredicateBody(HttpRequestMessage request, ParameterExpression param) { Expression workingExpr = null; var type = param.Type; var queryPairs = request.GetQueryNameValuePairs(); foreach (var queryPair in queryPairs) { if (String.IsNullOrWhiteSpace(queryPair.Key)) { continue; } if (!queryPair.Key.StartsWith("filter.")) { continue; } if (queryPair.Key.StartsWith("filter.calculated.")) { continue; } var filterField = queryPair.Key.Substring(7); // Skip "filter." IResourceTypeRegistration registration; try { registration = _resourceTypeRegistry.GetRegistrationForType(type); } catch (TypeRegistrationNotFoundException) { throw JsonApiException.CreateForBadRequest("No registration exists for the specified type"); } var expr = GetPredicate(filterField, registration, param, queryPair.Value); workingExpr = workingExpr == null ? expr : Expression.AndAlso(workingExpr, expr); } return(workingExpr ?? Expression.Constant(true)); // No filters, so return everything }
private Expression GetPredicate(string filterField, IResourceTypeRegistration registration, ParameterExpression param, string queryValue) { if (filterField == "id") { return(GetPredicateBodyForProperty(registration.IdProperty, queryValue, param)); } var resourceTypeField = registration.GetFieldByName(filterField); if (resourceTypeField == null) { throw JsonApiException.CreateForBadRequest( string.Format("No attribute {0} exists on the specified type.", filterField)); } if (string.IsNullOrWhiteSpace(queryValue)) { queryValue = null; } // See if it is a field property var fieldModelProperty = resourceTypeField as ResourceTypeAttribute; if (fieldModelProperty != null) { return(GetPredicateBodyForField(fieldModelProperty, queryValue, param)); } // See if it is a relationship property var relationshipModelProperty = resourceTypeField as ResourceTypeRelationship; if (relationshipModelProperty != null) { return(GetPredicateBodyForRelationship(relationshipModelProperty, queryValue, param)); } throw JsonApiException.CreateForBadRequest( string.Format("The attribute {0} is unsupported for filtering.", filterField)); }
private Expression GetPredicateBodyForRelationship(ResourceTypeRelationship resourceTypeProperty, string queryValue, ParameterExpression param) { var relatedType = resourceTypeProperty.RelatedType; PropertyInfo relatedIdProperty; try { var registration = _resourceTypeRegistry.GetRegistrationForType(relatedType); relatedIdProperty = registration.IdProperty; } catch (TypeRegistrationNotFoundException) { throw JsonApiException.CreateForBadRequest("No registration exists for the specified type"); } var prop = resourceTypeProperty.Property; if (resourceTypeProperty.IsToMany) { var propertyExpr = Expression.Property(param, prop); if (string.IsNullOrWhiteSpace(queryValue)) { var leftExpr = Expression.Equal(propertyExpr, Expression.Constant(null)); var asQueryableCallExpr = Expression.Call( typeof(Queryable), "AsQueryable", new[] { relatedType }, propertyExpr); var anyCallExpr = Expression.Call( typeof(Queryable), "Any", new[] { relatedType }, asQueryableCallExpr); var rightExpr = Expression.Not(anyCallExpr); return(Expression.OrElse(leftExpr, rightExpr)); } else { var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null)); var idValue = queryValue.Trim(); var idExpr = Expression.Constant(idValue); var anyParam = Expression.Parameter(relatedType); var relatedIdPropertyExpr = Expression.Property(anyParam, relatedIdProperty); var relatedIdPropertyEqualsIdExpr = Expression.Equal(relatedIdPropertyExpr, idExpr); var anyPredicateExpr = Expression.Lambda(relatedIdPropertyEqualsIdExpr, anyParam); var asQueryableCallExpr = Expression.Call( typeof(Queryable), "AsQueryable", new[] { relatedType }, propertyExpr); var rightExpr = Expression.Call( typeof(Queryable), "Any", new[] { relatedType }, asQueryableCallExpr, anyPredicateExpr); return(Expression.AndAlso(leftExpr, rightExpr)); } } else { var propertyExpr = Expression.Property(param, prop); if (string.IsNullOrWhiteSpace(queryValue)) { return(Expression.Equal(propertyExpr, Expression.Constant(null))); } var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null)); var idValue = queryValue.Trim(); var idExpr = Expression.Constant(idValue); var relatedIdPropertyExpr = Expression.Property(propertyExpr, relatedIdProperty); var rightExpr = Expression.Equal(relatedIdPropertyExpr, idExpr); return(Expression.AndAlso(leftExpr, rightExpr)); } }