1- using System ;
21using 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 ;
92
103namespace JsonApiDotNetCore . Internal . Query
114{
125 public class QuerySet
136 {
14- private readonly IJsonApiContext _jsonApiContext ;
15-
16- public QuerySet (
17- IJsonApiContext jsonApiContext ,
18- IQueryCollection query )
19- {
20- _jsonApiContext = jsonApiContext ;
21- BuildQuerySet ( query ) ;
22- }
23-
247 public List < FilterQuery > Filters { get ; set ; } = new List < FilterQuery > ( ) ;
258 public PageQuery PageQuery { get ; set ; } = new PageQuery ( ) ;
269 public List < SortQuery > SortParameters { get ; set ; } = new List < SortQuery > ( ) ;
2710 public List < string > IncludedRelationships { get ; set ; } = new List < string > ( ) ;
2811 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- }
19212 }
19313}
0 commit comments