Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5717f30

Browse files
Pass FilterQuery to GetQueryFilters
1 parent 11fe0da commit 5717f30

File tree

4 files changed

+109
-2
lines changed

4 files changed

+109
-2
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
using System.Collections.Generic;
2+
using System.Linq;
23
using JsonApiDotNetCore.Models;
34
using JsonApiDotNetCoreExample.Models;
5+
using JsonApiDotNetCore.Internal.Query;
46

57
namespace JsonApiDotNetCoreExample.Resources
68
{
79
public class UserResource : ResourceDefinition<User>
810
{
911
protected override List<AttrAttribute> OutputAttrs()
1012
=> Remove(user => user.Password);
13+
14+
public override QueryFilters GetQueryFilters()
15+
{
16+
return new QueryFilters
17+
{
18+
{ "first-character", (users, queryFilter) => FirstCharacterFilter(users, queryFilter) }
19+
};
20+
}
21+
22+
private IQueryable<User> FirstCharacterFilter(IQueryable<User> users, FilterQuery filterQuery)
23+
{
24+
switch(filterQuery.Operation)
25+
{
26+
case "lt":
27+
return users.Where(u => u.Username[0] < filterQuery.Value[0]);
28+
default:
29+
return users.Where(u => u.Username[0] == filterQuery.Value[0]);
30+
}
31+
}
1132
}
1233
}

‎src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public virtual IQueryable<TEntity> Filter(IQueryable<TEntity> entities, FilterQu
108108
var defaultQueryFilters = _resourceDefinition.GetQueryFilters();
109109
if (defaultQueryFilters != null && defaultQueryFilters.TryGetValue(filterQuery.Attribute, out var defaultQueryFilter) == true)
110110
{
111-
return defaultQueryFilter(entities, filterQuery.Value);
111+
return defaultQueryFilter(entities, filterQuery);
112112
}
113113
}
114114

‎src/JsonApiDotNetCore/Models/ResourceDefinition.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ private List<AttrAttribute> GetOutputAttrs()
162162
/// method signature.
163163
/// See <see cref="GetQueryFilters" /> for usage details.
164164
/// </summary>
165-
public class QueryFilters : Dictionary<string, Func<IQueryable<T>, string, IQueryable<T>>> { }
165+
public class QueryFilters : Dictionary<string, Func<IQueryable<T>, FilterQuery, IQueryable<T>>> { }
166166

167167
/// <summary>
168168
/// Define a the default sort order if no sort key is provided.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
using System.Threading.Tasks;
7+
using Bogus;
8+
using JsonApiDotNetCore.Models;
9+
using JsonApiDotNetCore.Serialization;
10+
using JsonApiDotNetCoreExample.Data;
11+
using JsonApiDotNetCoreExample.Models;
12+
using Microsoft.EntityFrameworkCore;
13+
using Newtonsoft.Json;
14+
using Xunit;
15+
16+
namespace JsonApiDotNetCoreExampleTests.Acceptance
17+
{
18+
[Collection("WebHostCollection")]
19+
public class QueryFiltersTests
20+
{
21+
private TestFixture<TestStartup> _fixture;
22+
private AppDbContext _context;
23+
private Faker<User> _userFaker;
24+
25+
public QueryFiltersTests(TestFixture<TestStartup> fixture)
26+
{
27+
_fixture = fixture;
28+
_context = fixture.GetService<AppDbContext>();
29+
_userFaker = new Faker<User>()
30+
.RuleFor(u => u.Username, f => f.Internet.UserName())
31+
.RuleFor(u => u.Password, f => f.Internet.Password());
32+
}
33+
34+
[Fact]
35+
public async Task FiltersWithCustomQueryFiltersEquals()
36+
{
37+
// Arrange
38+
var user = _userFaker.Generate();
39+
var firstUsernameCharacter = user.Username[0];
40+
_context.Users.Add(user);
41+
_context.SaveChanges();
42+
43+
var httpMethod = new HttpMethod("GET");
44+
var route = $"/api/v1/users?filter[first-character]=eq:{firstUsernameCharacter}";
45+
var request = new HttpRequestMessage(httpMethod, route);
46+
47+
// Act
48+
var response = await _fixture.Client.SendAsync(request);
49+
50+
// Assert
51+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
52+
var body = await response.Content.ReadAsStringAsync();
53+
var deserializedBody = _fixture.GetService<IJsonApiDeSerializer>().DeserializeList<User>(body);
54+
var usersWithFirstCharacter = _context.Users.Where(u => u.Username[0] == firstUsernameCharacter);
55+
Assert.True(deserializedBody.All(u => u.Username[0] == firstUsernameCharacter));
56+
}
57+
58+
[Fact]
59+
public async Task FiltersWithCustomQueryFiltersLessThan()
60+
{
61+
// Arrange
62+
var aUser = _userFaker.Generate();
63+
aUser.Username = "alfred";
64+
var zUser = _userFaker.Generate();
65+
zUser.Username = "zac";
66+
_context.Users.AddRange(aUser, zUser);
67+
_context.SaveChanges();
68+
69+
var median = 'h';
70+
71+
var httpMethod = new HttpMethod("GET");
72+
var route = $"/api/v1/users?filter[first-character]=lt:{median}";
73+
var request = new HttpRequestMessage(httpMethod, route);
74+
75+
// Act
76+
var response = await _fixture.Client.SendAsync(request);
77+
78+
// Assert
79+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
80+
var body = await response.Content.ReadAsStringAsync();
81+
var deserializedBody = _fixture.GetService<IJsonApiDeSerializer>().DeserializeList<User>(body);
82+
var usersBeforeMedian = _context.Users.Where(u => u.Username[0] < median);
83+
Assert.True(deserializedBody.All(u => u.Username[0] < median));
84+
}
85+
}
86+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /