1- using System ;
2- using System . IO ;
3- using System . Text . Json . Nodes ; // for JsonValue
4- using Microsoft . AspNetCore . Builder ;
1+ using Microsoft . AspNetCore . Builder ;
52using Microsoft . AspNetCore . Http ;
3+ using Microsoft . AspNetCore . Mvc ;
64using Microsoft . AspNetCore . Routing ;
75using Microsoft . Extensions . DependencyInjection ;
8- using Newtonsoft . Json ;
9- using Newtonsoft . Json . Linq ;
106
117namespace Infragistics . QueryBuilder . Executor
128{
139 public static class QueryExecutorExtensions
1410 {
15- public static IServiceCollection AddQueryBuilder < TMyDbContext , TResults > ( this IServiceCollection services )
16- where TResults : class
11+ public static IServiceCollection AddQueryBuilder < TMyDbContext , TResults > ( this IServiceCollection services ) where TResults : class
1712 {
1813 services . AddScoped < QueryBuilderService < TMyDbContext , TResults > > ( ) ;
1914 return services ;
2015 }
2116
22- public static IEndpointRouteBuilder UseQueryBuilder < TMyDbContext , TResults > (
23- this IEndpointRouteBuilder endpoints , string path )
24- where TMyDbContext : class
25- where TResults : class
17+ public static IEndpointRouteBuilder UseQueryBuilder < TMyDbContext , TResults > ( this IEndpointRouteBuilder endpoints , string path ) where TMyDbContext : class where TResults : class
2618 {
27- endpoints . MapPost ( path , async ( HttpContext ctx , QueryBuilderService < TMyDbContext , TResults > svc ) =>
19+ endpoints . MapPost ( path , ( [ FromBody ] Query query , QueryBuilderService < TMyDbContext , TResults > queryBuilderService ) =>
2820 {
29- string json ;
30- using ( var sr = new StreamReader ( ctx . Request . Body ) )
21+ if ( query != null )
3122 {
32- json = await sr . ReadToEndAsync ( ) ;
23+ var result = queryBuilderService . RunQuery ( query ) ;
24+ return Results . Ok ( result ) ;
3325 }
34-
35- var settings = new Newtonsoft . Json . JsonSerializerSettings
26+ else
3627 {
37- DateParseHandling = Newtonsoft . Json . DateParseHandling . None ,
38- ReferenceLoopHandling = Newtonsoft . Json . ReferenceLoopHandling . Ignore ,
39- } ;
40-
41- // 1) Convert QueryFilter by shape (tree vs leaf)
42- settings . Converters . Add ( new QueryFilterCreationConverter ( ) ) ;
43- // 2) Let Newtonsoft write primitives (number/string/bool) into System.Text.Json.Nodes.JsonValue
44- settings . Converters . Add ( new NewtonsoftJsonValueConverter ( ) ) ;
45-
46- var query = Newtonsoft . Json . JsonConvert . DeserializeObject < Query > ( json , settings ) ;
47- if ( query is null )
4828 return Results . BadRequest ( "Wrong or missing query" ) ;
49-
50- var result = svc . RunQuery ( query ) ;
51- return Results . Ok ( result ) ;
52- } )
53- . WithTags ( [ "QueryBuilder" ] )
54- . Accepts < Query > ( "application/json" )
55- . Produces < TResults > ( ) ;
56-
29+ }
30+ } ) . WithTags ( [ "QueryBuilder" ] ) . Accepts < Query > ( "application/json" ) . Produces < TResults > ( ) ;
5731 return endpoints ;
5832 }
5933 }
60-
61- /// <summary>
62- /// Resolves QueryFilter to the only concrete types available:
63- /// - FilteringExpressionsTree (has "filteringOperands")
64- /// - FilteringExpression (leaf)
65- /// </summary>
66- file sealed class QueryFilterCreationConverter : Newtonsoft . Json . JsonConverter
67- {
68- private static readonly Type BaseType = typeof ( QueryFilter ) ;
69- private static readonly Type TreeType = typeof ( FilteringExpressionsTree ) ;
70- private static readonly Type LeafType = typeof ( FilteringExpression ) ;
71-
72- public override bool CanConvert ( Type objectType ) => objectType == BaseType ;
73-
74- public override object ReadJson (
75- Newtonsoft . Json . JsonReader reader ,
76- Type objectType ,
77- object ? existingValue ,
78- Newtonsoft . Json . JsonSerializer serializer )
79- {
80- var jo = JObject . Load ( reader ) ;
81-
82- // Tree if it has an array "filteringOperands"; otherwise leaf
83- var isTree = jo [ "filteringOperands" ] is JArray ;
84- var target = isTree ? TreeType : LeafType ;
85-
86- return jo . ToObject ( target , serializer ) ! ;
87- }
88-
89- public override void WriteJson (
90- Newtonsoft . Json . JsonWriter writer ,
91- object ? value ,
92- Newtonsoft . Json . JsonSerializer serializer )
93- {
94- serializer . Serialize ( writer , value ) ;
95- }
96- }
97-
98- /// <summary>
99- /// Newtonsoft -> System.Text.Json.Nodes.JsonValue bridge.
100- /// Handles primitives and null (which is all your payload needs for "searchVal": 10253).
101- /// </summary>
102- file sealed class NewtonsoftJsonValueConverter : Newtonsoft . Json . JsonConverter
103- {
104- public override bool CanConvert ( Type objectType )
105- => objectType == typeof ( JsonValue ) ;
106-
107- public override object ? ReadJson (
108- Newtonsoft . Json . JsonReader reader ,
109- Type objectType ,
110- object ? existingValue ,
111- Newtonsoft . Json . JsonSerializer serializer )
112- {
113- if ( reader . TokenType == Newtonsoft . Json . JsonToken . Null )
114- return null ;
115-
116- // Extract the raw .NET value from Newtonsoft token
117- var token = JToken . ReadFrom ( reader ) ;
118-
119- // For numbers/bools/strings, token.ToObject<object>() is a primitive -> wrap it
120- // For safety, we only support primitives here since JsonValue is a primitive wrapper.
121- // (Your payload uses numbers/strings/null for searchVal.)
122- var primitive = token . Type switch
123- {
124- JTokenType . Integer => ( object ) token . ToObject < long > ( ) ! ,
125- JTokenType . Float => token . ToObject < double > ( ) ! ,
126- JTokenType . Boolean => token . ToObject < bool > ( ) ! ,
127- JTokenType . String => token . ToObject < string > ( ) ! ,
128- JTokenType . Null => null ! ,
129- _ => throw new NotSupportedException (
130- $ "JsonValue converter only supports primitives. Got { token . Type } .")
131- } ;
132-
133- return primitive is null ? null : JsonValue . Create ( primitive ) ;
134- }
135-
136- public override void WriteJson (
137- Newtonsoft . Json . JsonWriter writer ,
138- object ? value ,
139- Newtonsoft . Json . JsonSerializer serializer )
140- {
141- if ( value is null )
142- {
143- writer . WriteNull ( ) ;
144- return ;
145- }
146-
147- var jv = ( JsonValue ) value ;
148- // Extract the underlying primitive and write it as a native JSON value
149- if ( jv . TryGetValue ( out long l ) ) { writer . WriteValue ( l ) ; return ; }
150- if ( jv . TryGetValue ( out double d ) ) { writer . WriteValue ( d ) ; return ; }
151- if ( jv . TryGetValue ( out bool b ) ) { writer . WriteValue ( b ) ; return ; }
152- if ( jv . TryGetValue ( out string s ) ) { writer . WriteValue ( s ) ; return ; }
153-
154- // Fallback: write as string representation
155- writer . WriteValue ( jv . ToJsonString ( ) ) ;
156- }
157- }
158- }
34+ }
0 commit comments