1
- using System ;
2
1
using System . Collections . Generic ;
3
- using System . Linq ;
4
- using JsonApiDotNetCore . Extensions ;
5
- using JsonApiDotNetCore . Services ;
6
- using Microsoft . AspNetCore . Http ;
7
- using JsonApiDotNetCore . Models ;
8
- using JsonApiDotNetCore . Controllers ;
9
2
10
3
namespace JsonApiDotNetCore . Internal . Query
11
4
{
12
5
public class QuerySet
13
6
{
14
- private readonly IJsonApiContext _jsonApiContext ;
15
-
16
- public QuerySet (
17
- IJsonApiContext jsonApiContext ,
18
- IQueryCollection query )
19
- {
20
- _jsonApiContext = jsonApiContext ;
21
- BuildQuerySet ( query ) ;
22
- }
23
-
24
7
public List < FilterQuery > Filters { get ; set ; } = new List < FilterQuery > ( ) ;
25
8
public PageQuery PageQuery { get ; set ; } = new PageQuery ( ) ;
26
9
public List < SortQuery > SortParameters { get ; set ; } = new List < SortQuery > ( ) ;
27
10
public List < string > IncludedRelationships { get ; set ; } = new List < string > ( ) ;
28
11
public List < string > Fields { get ; set ; } = new List < string > ( ) ;
29
-
30
- private void BuildQuerySet ( IQueryCollection query )
31
- {
32
- var disabledQueries = _jsonApiContext . GetControllerAttribute < DisableQueryAttribute > ( ) ? . QueryParams ?? QueryParams . None ;
33
-
34
- foreach ( var pair in query )
35
- {
36
- if ( pair . Key . StartsWith ( "filter" ) )
37
- {
38
- if ( disabledQueries . HasFlag ( QueryParams . Filter ) == false )
39
- Filters . AddRange ( ParseFilterQuery ( pair . Key , pair . Value ) ) ;
40
- continue ;
41
- }
42
-
43
- if ( pair . Key . StartsWith ( "sort" ) )
44
- {
45
- if ( disabledQueries . HasFlag ( QueryParams . Sort ) == false )
46
- SortParameters = ParseSortParameters ( pair . Value ) ;
47
- continue ;
48
- }
49
-
50
- if ( pair . Key . StartsWith ( "include" ) )
51
- {
52
- if ( disabledQueries . HasFlag ( QueryParams . Include ) == false )
53
- IncludedRelationships = ParseIncludedRelationships ( pair . Value ) ;
54
- continue ;
55
- }
56
-
57
- if ( pair . Key . StartsWith ( "page" ) )
58
- {
59
- if ( disabledQueries . HasFlag ( QueryParams . Page ) == false )
60
- PageQuery = ParsePageQuery ( pair . Key , pair . Value ) ;
61
- continue ;
62
- }
63
-
64
- if ( pair . Key . StartsWith ( "fields" ) )
65
- {
66
- if ( disabledQueries . HasFlag ( QueryParams . Fields ) == false )
67
- Fields = ParseFieldsQuery ( pair . Key , pair . Value ) ;
68
- continue ;
69
- }
70
-
71
- if ( _jsonApiContext . Options . AllowCustomQueryParameters == false )
72
- throw new JsonApiException ( 400 , $ "{ pair } is not a valid query.") ;
73
- }
74
- }
75
-
76
- private List < FilterQuery > ParseFilterQuery ( string key , string value )
77
- {
78
- // expected input = filter[id]=1
79
- // expected input = filter[id]=eq:1
80
- var queries = new List < FilterQuery > ( ) ;
81
-
82
- var propertyName = key . Split ( '[' , ']' ) [ 1 ] . ToProperCase ( ) ;
83
-
84
- var values = value . Split ( ',' ) ;
85
- foreach ( var val in values )
86
- {
87
- ( var operation , var filterValue ) = ParseFilterOperation ( val ) ;
88
- queries . Add ( new FilterQuery ( propertyName , filterValue , operation ) ) ;
89
- }
90
-
91
- return queries ;
92
- }
93
-
94
- private ( string operation , string value ) ParseFilterOperation ( string value )
95
- {
96
- if ( value . Length < 3 )
97
- return ( string . Empty , value ) ;
98
-
99
- var operation = value . Split ( ':' ) ;
100
-
101
- if ( operation . Length == 1 )
102
- return ( string . Empty , value ) ;
103
-
104
- // remove prefix from value
105
- if ( Enum . TryParse ( operation [ 0 ] , out FilterOperations op ) == false )
106
- return ( string . Empty , value ) ;
107
-
108
- var prefix = operation [ 0 ] ;
109
- value = string . Join ( ":" , operation . Skip ( 1 ) ) ;
110
-
111
- return ( prefix , value ) ;
112
- }
113
-
114
- private PageQuery ParsePageQuery ( string key , string value )
115
- {
116
- // expected input = page[size]=10
117
- // page[number]=1
118
- PageQuery = PageQuery ?? new PageQuery ( ) ;
119
-
120
- var propertyName = key . Split ( '[' , ']' ) [ 1 ] ;
121
-
122
- if ( propertyName == "size" )
123
- PageQuery . PageSize = Convert . ToInt32 ( value ) ;
124
- else if ( propertyName == "number" )
125
- PageQuery . PageOffset = Convert . ToInt32 ( value ) ;
126
-
127
- return PageQuery ;
128
- }
129
-
130
- // sort=id,name
131
- // sort=-id
132
- private List < SortQuery > ParseSortParameters ( string value )
133
- {
134
- var sortParameters = new List < SortQuery > ( ) ;
135
- value . Split ( ',' ) . ToList ( ) . ForEach ( p =>
136
- {
137
- var direction = SortDirection . Ascending ;
138
- if ( p [ 0 ] == '-' )
139
- {
140
- direction = SortDirection . Descending ;
141
- p = p . Substring ( 1 ) ;
142
- }
143
-
144
- var attribute = GetAttribute ( p . ToProperCase ( ) ) ;
145
-
146
- sortParameters . Add ( new SortQuery ( direction , attribute ) ) ;
147
- } ) ;
148
-
149
- return sortParameters ;
150
- }
151
-
152
- private List < string > ParseIncludedRelationships ( string value )
153
- {
154
- if ( value . Contains ( "." ) )
155
- throw new JsonApiException ( 400 , "Deeply nested relationships are not supported" ) ;
156
-
157
- return value
158
- . Split ( ',' )
159
- . ToList ( ) ;
160
- }
161
-
162
- private List < string > ParseFieldsQuery ( string key , string value )
163
- {
164
- // expected: fields[TYPE]=prop1,prop2
165
- var typeName = key . Split ( '[' , ']' ) [ 1 ] ;
166
-
167
- var includedFields = new List < string > { "Id" } ;
168
-
169
- if ( typeName != _jsonApiContext . RequestEntity . EntityName )
170
- return includedFields ;
171
-
172
- var fields = value . Split ( ',' ) ;
173
- foreach ( var field in fields )
174
- {
175
- var internalAttrName = _jsonApiContext . RequestEntity
176
- . Attributes
177
- . SingleOrDefault ( attr => attr . PublicAttributeName == field )
178
- . InternalAttributeName ;
179
- includedFields . Add ( internalAttrName ) ;
180
- }
181
-
182
- return includedFields ;
183
- }
184
-
185
- private AttrAttribute GetAttribute ( string propertyName )
186
- {
187
- return _jsonApiContext . RequestEntity . Attributes
188
- . FirstOrDefault ( attr =>
189
- attr . InternalAttributeName . ToLower ( ) == propertyName . ToLower ( )
190
- ) ;
191
- }
192
12
}
193
13
}
0 commit comments