In my project currently i have implemented multiple searching using below function code:
public static IQueryable<T> Filter<T>(this IQueryable<T> source, SearchCriteria searchCriteria)
{
var predicate = new DynamicFilterBuilder<T>();
foreach (var item in searchCriteria.filters)
{
if (!string.IsNullOrEmpty(item.key))
{
if (item.key == "CreatedOn")
predicate.And(item.key, DynamicExpressions.FilterOperator.GreaterThanOrEqual, DateTime.ParseExact(item.value.ToString() " 00:00:00", "yyyy-MM-dd HH:mm:ss", null))
.And(item.key, DynamicExpressions.FilterOperator.LessThanOrEqual, DateTime.ParseExact(item.value.ToString() " 23:59:59", "yyyy-MM-dd HH:mm:ss", null));
else
predicate.And(item.key,
DynamicExpressions.FilterOperator.Contains, item.value);
}
}
return source.Where(predicate.Build());
}
But it's working only like Case sensitive means i need to pass exactly Name ex : "Data" if i passed "data" it's not returning anything so can someone help me on this ?
CodePudding user response:
You can do a lower case conversion here and compare with a lowercase like below:
if (item.key.ToLower() == "createdon")
{
//Your stuff
}
CodePudding user response:
The package from zHaytam mentioned in the comment ( github.com/zHaytam/DynamicExpressions) is open source on GitHub so we can see that in its implementation (Class DynamicExpressions), the expressions are delegating to Linq expressions:
private static Expression CreateFilter(MemberExpression prop, FilterOperator op, ConstantExpression constant)
{
return op switch
{
FilterOperator.Equals => Expression.Equal(prop, constant),
FilterOperator.GreaterThan => Expression.GreaterThan(prop, constant),
FilterOperator.LessThan => Expression.LessThan(prop, constant),
FilterOperator.Contains => Expression.Call(prop, _containsMethod, PrepareConstant(constant)),
FilterOperator.StartsWith => Expression.Call(prop, _startsWithMethod, PrepareConstant(constant)),
FilterOperator.EndsWith => Expression.Call(prop, _endsWithMethod, PrepareConstant(constant)),
FilterOperator.DoesntEqual => Expression.NotEqual(prop, constant),
FilterOperator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(prop, constant),
FilterOperator.LessThanOrEqual => Expression.LessThanOrEqual(prop, constant),
_ => throw new NotImplementedException()
};
}
and the containsMethod
uses the version public bool Contains (string value);
of string.Contains
:
private static readonly MethodInfo _containsMethod = typeof(string).GetMethod("Contains"
, new Type[] { typeof(string) });
To make the "Contains" method become case-insensitive, I think you can download and modify zHaytam's code:
In method DynamicExpressions
modify the initialization expression of _containsMethod
to reference the public bool Contains (string value, StringComparison comparisonType)
version of string.Contains
:
private static readonly MethodInfo _containsMethod = typeof(string).GetMethod("Contains"
, new Type[] { typeof(string), typeof(StringComparison) });
and modify the CreateFilter
method to provide the additional parameter to ignore case:
FilterOperator.Contains => Expression.Call(prop, _containsMethod, PrepareConstant(constant), Expression.Constant(StringComparison.OrdinalIgnoreCase)),