Skip to content

Commit 5a3afc2

Browse files
committed
Making the filtering robust when doing filtering of nullable strings aka string?
1 parent d6928de commit 5a3afc2

File tree

1 file changed

+29
-29
lines changed

1 file changed

+29
-29
lines changed

eFormApi.BasePn/Infrastructure/Extensions/OrderedQueryableExtensions.cs

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static IOrderedQueryable<TSource> CustomOrderBy<TSource>(
4444
.Where(m =>
4545
{
4646
var parameters = m.GetParameters().ToList();
47-
//Put more restriction here to ensure selecting the right overload
47+
//Put more restriction here to ensure selecting the right overload
4848
return parameters.Count == 2; //overload that has 2 parameters
4949
}).Single();
5050
//The linq's OrderBy<TSource, TKey> has two generic types, which provided here
@@ -76,7 +76,7 @@ public static IOrderedQueryable<TSource> CustomOrderByDescending<TSource>(
7676
.Where(m =>
7777
{
7878
var parameters = m.GetParameters().ToList();
79-
//Put more restriction here to ensure selecting the right overload
79+
//Put more restriction here to ensure selecting the right overload
8080
return parameters.Count == 2; //overload that has 2 parameters
8181
}).Single();
8282
//The linq's OrderByDescending<TSource, TKey> has two generic types, which provided here
@@ -129,53 +129,53 @@ public static IQueryable<TSource> CustomFiltering<TSource>(
129129

130130
// foreach on all fields on entity type and take only string type fields and fields, whose names were transmitted
131131
foreach (var prop in typeof(TSource).GetProperties().Where(x =>
132-
propertyNames.Contains(x.Name) && (x.PropertyType == typeof(string) ||
133-
x.PropertyType == typeof(int?) ||
134-
x.PropertyType == typeof(DateTime?) ||
135-
x.PropertyType == typeof(int) ||
136-
x.PropertyType == typeof(DateTime))))
132+
propertyNames.Contains(x.Name) && (x.PropertyType == typeof(string) ||
133+
x.PropertyType == typeof(int?) ||
134+
x.PropertyType == typeof(DateTime?) ||
135+
x.PropertyType == typeof(int) ||
136+
x.PropertyType == typeof(DateTime))))
137137
{
138-
// x => x.propName
139138
var memberExpression = Expression.PropertyOrField(parameter, prop.Name);
140139

141-
// if type prop not string - need to call ToString()
142-
MethodCallExpression toStringCall;
140+
MethodCallExpression toStringCall = null;
143141
if (prop.PropertyType == typeof(DateTime))
144142
{
145-
// x.propName.ToString()
146-
toStringCall = Expression.Call(memberExpression,dateTimeToStringMethod);
143+
toStringCall = Expression.Call(memberExpression, dateTimeToStringMethod);
147144
}
148145
else if (prop.PropertyType == typeof(DateTime?))
149146
{
150-
// x.propName.ToString()
151147
toStringCall = Expression.Call(memberExpression, nullebleDateTimeToStringMethod);
152148
}
153149
else if (prop.PropertyType == typeof(int?))
154150
{
155-
// x.propName.ToString()
156151
toStringCall = Expression.Call(memberExpression, nullebleIntToStringMethod);
157152
}
158153
else if (prop.PropertyType == typeof(int))
159154
{
160-
// x.propName.ToString()
161155
toStringCall = Expression.Call(memberExpression, intToStringMethod);
162156
}
163-
else
164-
{
165-
// prop is string. not need call ToString()
166-
toStringCall = null;
167-
}
168157

169-
// string valueExpression = filter;
170158
var valueExpression = Expression.Constant(filter.ToUpper(), typeof(string));
171159

172-
// x.propName(x.propName is string ? none : .ToString()).ToUpper()
173-
var toUpperExpression = Expression.Call(toStringCall == null ? memberExpression : toStringCall, toUpperMethod);
174-
175-
// x.propName(x.propName is string ? none : .ToString()).ToUpper().Contains(filter.ToUpper())
176-
var containsExpression = Expression.Call(toUpperExpression, containsMethod, valueExpression);
177-
178-
expressions.Add(containsExpression);
160+
if (prop.PropertyType == typeof(string))
161+
{
162+
// x.propName != null
163+
var notNull = Expression.NotEqual(memberExpression, Expression.Constant(null, typeof(string)));
164+
// x.propName.ToUpper()
165+
var toUpperExpression = Expression.Call(memberExpression, toUpperMethod);
166+
// x.propName.ToUpper().Contains(filter.ToUpper())
167+
var containsExpression = Expression.Call(toUpperExpression, containsMethod, valueExpression);
168+
// x.propName != null && x.propName.ToUpper().Contains(filter.ToUpper())
169+
var safeContains = Expression.AndAlso(notNull, containsExpression);
170+
expressions.Add(safeContains);
171+
}
172+
else
173+
{
174+
// x.propName.ToString().ToUpper().Contains(filter.ToUpper())
175+
var toUpperExpression = Expression.Call(toStringCall, toUpperMethod);
176+
var containsExpression = Expression.Call(toUpperExpression, containsMethod, valueExpression);
177+
expressions.Add(containsExpression);
178+
}
179179
}
180180

181181
// if not need filtration - return
@@ -190,7 +190,7 @@ public static IQueryable<TSource> CustomFiltering<TSource>(
190190
// and start from 1 add contains like x.Name.Contains(filter) || x.Description.Contains(filter) || ...
191191
for (var i = 1; i < expressions.Count; i++)
192192
{
193-
orExpression = Expression.OrElse(orExpression, expressions[i]);
193+
orExpression = Expression.Or(orExpression, expressions[i]);
194194
}
195195

196196
// x.Name or x.Description - **example**

0 commit comments

Comments
 (0)