3
3
using System . Linq ;
4
4
using JsonApiDotNetCore . Configuration ;
5
5
using JsonApiDotNetCore . Controllers ;
6
- using JsonApiDotNetCore . Extensions ;
7
6
using JsonApiDotNetCore . Internal ;
8
7
using JsonApiDotNetCore . Internal . Query ;
9
8
using JsonApiDotNetCore . Models ;
@@ -18,8 +17,17 @@ public class QueryParser : IQueryParser {
18
17
private readonly IControllerContext _controllerContext ;
19
18
private readonly JsonApiOptions _options ;
20
19
20
+ private const string FILTER = "filter" ;
21
+ private const string SORT = "sort" ;
22
+ private const string INCLUDE = "include" ;
23
+ private const string PAGE = "page" ;
24
+ private const string FIELDS = "fields" ;
21
25
private const char OPEN_BRACKET = '[' ;
22
26
private const char CLOSE_BRACKET = ']' ;
27
+ private const char COMMA = ',' ;
28
+ private const char COLON = ':' ;
29
+ private const string COLON_STR = ":" ;
30
+
23
31
public QueryParser (
24
32
IControllerContext controllerContext ,
25
33
JsonApiOptions options ) {
@@ -32,31 +40,31 @@ public virtual QuerySet Parse(IQueryCollection query) {
32
40
var disabledQueries = _controllerContext . GetControllerAttribute < DisableQueryAttribute > ( ) ? . QueryParams ?? QueryParams . None ;
33
41
34
42
foreach ( var pair in query ) {
35
- if ( pair . Key . StartsWith ( "filter" ) ) {
43
+ if ( pair . Key . StartsWith ( FILTER ) ) {
36
44
if ( disabledQueries . HasFlag ( QueryParams . Filter ) == false )
37
45
querySet . Filters . AddRange ( ParseFilterQuery ( pair . Key , pair . Value ) ) ;
38
46
continue ;
39
47
}
40
48
41
- if ( pair . Key . StartsWith ( "sort" ) ) {
49
+ if ( pair . Key . StartsWith ( SORT ) ) {
42
50
if ( disabledQueries . HasFlag ( QueryParams . Sort ) == false )
43
51
querySet . SortParameters = ParseSortParameters ( pair . Value ) ;
44
52
continue ;
45
53
}
46
54
47
- if ( pair . Key . StartsWith ( "include" ) ) {
55
+ if ( pair . Key . StartsWith ( INCLUDE ) ) {
48
56
if ( disabledQueries . HasFlag ( QueryParams . Include ) == false )
49
57
querySet . IncludedRelationships = ParseIncludedRelationships ( pair . Value ) ;
50
58
continue ;
51
59
}
52
60
53
- if ( pair . Key . StartsWith ( "page" ) ) {
61
+ if ( pair . Key . StartsWith ( PAGE ) ) {
54
62
if ( disabledQueries . HasFlag ( QueryParams . Page ) == false )
55
63
querySet . PageQuery = ParsePageQuery ( querySet . PageQuery , pair . Key , pair . Value ) ;
56
64
continue ;
57
65
}
58
66
59
- if ( pair . Key . StartsWith ( "fields" ) ) {
67
+ if ( pair . Key . StartsWith ( FIELDS ) ) {
60
68
if ( disabledQueries . HasFlag ( QueryParams . Fields ) == false )
61
69
querySet . Fields = ParseFieldsQuery ( pair . Key , pair . Value ) ;
62
70
continue ;
@@ -76,10 +84,9 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
76
84
77
85
var propertyName = key . Split ( OPEN_BRACKET , CLOSE_BRACKET ) [ 1 ] ;
78
86
79
- var values = value . Split ( ',' ) ;
87
+ var values = value . Split ( COMMA ) ;
80
88
foreach ( var val in values ) {
81
- ( var operation ,
82
- var filterValue ) = ParseFilterOperation ( val ) ;
89
+ ( var operation , var filterValue ) = ParseFilterOperation ( val ) ;
83
90
queries . Add ( new FilterQuery ( propertyName , filterValue , operation ) ) ;
84
91
}
85
92
@@ -90,7 +97,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
90
97
if ( value . Length < 3 )
91
98
return ( string . Empty , value ) ;
92
99
93
- var operation = value . Split ( ':' ) ;
100
+ var operation = value . Split ( COLON ) ;
94
101
95
102
if ( operation . Length == 1 )
96
103
return ( string . Empty , value ) ;
@@ -100,7 +107,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
100
107
return ( string . Empty , value ) ;
101
108
102
109
var prefix = operation [ 0 ] ;
103
- value = string . Join ( ":" , operation . Skip ( 1 ) ) ;
110
+ value = string . Join ( COLON_STR , operation . Skip ( 1 ) ) ;
104
111
105
112
return ( prefix , value ) ;
106
113
}
@@ -110,11 +117,14 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
110
117
// page[number]=1
111
118
pageQuery = pageQuery ?? new PageQuery ( ) ;
112
119
113
- var propertyName = key . Split ( '[' , ']' ) [ 1 ] ;
120
+ var propertyName = key . Split ( OPEN_BRACKET , CLOSE_BRACKET ) [ 1 ] ;
121
+
122
+ const string SIZE = "size" ;
123
+ const string NUMBER = "number" ;
114
124
115
- if ( propertyName == "size" )
125
+ if ( propertyName == SIZE )
116
126
pageQuery . PageSize = Convert . ToInt32 ( value ) ;
117
- else if ( propertyName == "number" )
127
+ else if ( propertyName == NUMBER )
118
128
pageQuery . PageOffset = Convert . ToInt32 ( value ) ;
119
129
120
130
return pageQuery ;
@@ -123,11 +133,11 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
123
133
// sort=id,name
124
134
// sort=-id
125
135
protected virtual List < SortQuery > ParseSortParameters ( string value ) {
126
- const char SORT_DELIMITER = ',' ;
136
+ var sortParameters = new List < SortQuery > ( ) ;
137
+
127
138
const char DESCENDING_SORT_OPERATOR = '-' ;
139
+ var sortSegments = value . Split ( COMMA ) ;
128
140
129
- var sortParameters = new List < SortQuery > ( ) ;
130
- var sortSegments = value . Split ( SORT_DELIMITER ) ;
131
141
foreach ( var sortSegment in sortSegments ) {
132
142
133
143
var propertyName = sortSegment ;
@@ -147,24 +157,26 @@ protected virtual List<SortQuery> ParseSortParameters(string value) {
147
157
}
148
158
149
159
protected virtual List < string > ParseIncludedRelationships ( string value ) {
150
- if ( value . Contains ( "." ) )
160
+ const string NESTED_DELIMITER = "." ;
161
+ if ( value . Contains ( NESTED_DELIMITER ) )
151
162
throw new JsonApiException ( 400 , "Deeply nested relationships are not supported" ) ;
152
163
153
164
return value
154
- . Split ( ',' )
165
+ . Split ( COMMA )
155
166
. ToList ( ) ;
156
167
}
157
168
158
169
protected virtual List < string > ParseFieldsQuery ( string key , string value ) {
159
170
// expected: fields[TYPE]=prop1,prop2
160
- var typeName = key . Split ( '[' , ']' ) [ 1 ] ;
171
+ var typeName = key . Split ( OPEN_BRACKET , CLOSE_BRACKET ) [ 1 ] ;
161
172
162
- var includedFields = new List < string > { "Id" } ;
173
+ const string ID = "Id" ;
174
+ var includedFields = new List < string > { ID } ;
163
175
164
176
if ( typeName != _controllerContext . RequestEntity . EntityName )
165
177
return includedFields ;
166
178
167
- var fields = value . Split ( ',' ) ;
179
+ var fields = value . Split ( COMMA ) ;
168
180
foreach ( var field in fields ) {
169
181
var internalAttrName = _controllerContext . RequestEntity
170
182
. Attributes
@@ -176,11 +188,17 @@ protected virtual List<string> ParseFieldsQuery(string key, string value) {
176
188
return includedFields ;
177
189
}
178
190
179
- protected virtual AttrAttribute GetAttribute ( string propertyName ) => _controllerContext
180
- . RequestEntity
181
- . Attributes
182
- . FirstOrDefault ( attr =>
183
- string . Equals ( attr . PublicAttributeName , propertyName , StringComparison . OrdinalIgnoreCase )
184
- ) ;
191
+ protected virtual AttrAttribute GetAttribute ( string propertyName ) {
192
+ try {
193
+ return _controllerContext
194
+ . RequestEntity
195
+ . Attributes
196
+ . Single ( attr =>
197
+ string . Equals ( attr . PublicAttributeName , propertyName , StringComparison . OrdinalIgnoreCase )
198
+ ) ;
199
+ } catch ( InvalidOperationException e ) {
200
+ throw new JsonApiException ( 400 , $ "Attribute '{ propertyName } ' does not exist on resource '{ _controllerContext . RequestEntity . EntityName } '") ;
201
+ }
202
+ }
185
203
}
186
204
}
0 commit comments