Skip to content

Commit d7c6353

Browse files
authored
Added value types support to the filters isnull & isnotnull. (#549) (#573)
1 parent 343912e commit d7c6353

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs

+20-2
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,29 @@ private static Expression GetFilterExpressionLambda(Expression left, Expression
160160
break;
161161
case FilterOperations.isnotnull:
162162
// {model.Id != null}
163-
body = Expression.NotEqual(left, right);
163+
if (left.Type.IsValueType &&
164+
!(left.Type.IsGenericType && left.Type.GetGenericTypeDefinition() == typeof(Nullable<>)))
165+
{
166+
var nullableType = typeof(Nullable<>).MakeGenericType(left.Type);
167+
body = Expression.NotEqual(Expression.Convert(left, nullableType), right);
168+
}
169+
else
170+
{
171+
body = Expression.NotEqual(left, right);
172+
}
164173
break;
165174
case FilterOperations.isnull:
166175
// {model.Id == null}
167-
body = Expression.Equal(left, right);
176+
if (left.Type.IsValueType &&
177+
!(left.Type.IsGenericType && left.Type.GetGenericTypeDefinition() == typeof(Nullable<>)))
178+
{
179+
var nullableType = typeof(Nullable<>).MakeGenericType(left.Type);
180+
body = Expression.Equal(Expression.Convert(left, nullableType), right);
181+
}
182+
else
183+
{
184+
body = Expression.Equal(left, right);
185+
}
168186
break;
169187
default:
170188
throw new JsonApiException(500, $"Unknown filter operation {operation}");

test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs

+60
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,36 @@ public async Task Can_Filter_TodoItems_Using_IsNotNull_Operator()
180180
Assert.All(todoItems, t => Assert.NotNull(t.UpdatedDate));
181181
}
182182

183+
[Fact]
184+
public async Task Can_Filter_TodoItems_ByParent_Using_IsNotNull_Operator()
185+
{
186+
// Arrange
187+
var todoItem = _todoItemFaker.Generate();
188+
todoItem.Assignee = new Person();
189+
190+
var otherTodoItem = _todoItemFaker.Generate();
191+
otherTodoItem.Assignee = null;
192+
193+
_context.TodoItems.AddRange(new[] { todoItem, otherTodoItem });
194+
_context.SaveChanges();
195+
196+
var httpMethod = new HttpMethod("GET");
197+
var route = $"/api/v1/todo-items?filter[assignee.id]=isnotnull:";
198+
var request = new HttpRequestMessage(httpMethod, route);
199+
200+
// Act
201+
var response = await _fixture.Client.SendAsync(request);
202+
203+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
204+
205+
var body = await response.Content.ReadAsStringAsync();
206+
var todoItems = _fixture.GetService<IJsonApiDeSerializer>().DeserializeList<TodoItem>(body);
207+
208+
// Assert
209+
Assert.NotEmpty(todoItems);
210+
Assert.All(todoItems, t => Assert.NotNull(t.Assignee));
211+
}
212+
183213
[Fact]
184214
public async Task Can_Filter_TodoItems_Using_IsNull_Operator()
185215
{
@@ -210,6 +240,36 @@ public async Task Can_Filter_TodoItems_Using_IsNull_Operator()
210240
Assert.All(todoItems, t => Assert.Null(t.UpdatedDate));
211241
}
212242

243+
[Fact]
244+
public async Task Can_Filter_TodoItems_ByParent_Using_IsNull_Operator()
245+
{
246+
// Arrange
247+
var todoItem = _todoItemFaker.Generate();
248+
todoItem.Assignee = null;
249+
250+
var otherTodoItem = _todoItemFaker.Generate();
251+
otherTodoItem.Assignee = new Person();
252+
253+
_context.TodoItems.AddRange(new[] { todoItem, otherTodoItem });
254+
_context.SaveChanges();
255+
256+
var httpMethod = new HttpMethod("GET");
257+
var route = $"/api/v1/todo-items?filter[assignee.id]=isnull:";
258+
var request = new HttpRequestMessage(httpMethod, route);
259+
260+
// Act
261+
var response = await _fixture.Client.SendAsync(request);
262+
263+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
264+
265+
var body = await response.Content.ReadAsStringAsync();
266+
var todoItems = _fixture.GetService<IJsonApiDeSerializer>().DeserializeList<TodoItem>(body);
267+
268+
// Assert
269+
Assert.NotEmpty(todoItems);
270+
Assert.All(todoItems, t => Assert.Null(t.Assignee));
271+
}
272+
213273
[Fact]
214274
public async Task Can_Filter_TodoItems_Using_Like_Operator()
215275
{

0 commit comments

Comments
 (0)