private async Task ExecuteAsync(HttpContext context, ISchemaFactory schemaService)
        {
            var schema = await schemaService.GetSchema();

            AbpGraphQLRequest request = null;

            if (HttpMethods.IsPost(context.Request.Method))
            {
                var mediaType = new MediaType(context.Request.ContentType);

                try
                {
                    if (mediaType.IsSubsetOf(JsonMediaType))
                    {
                        using (var sr = new StreamReader(context.Request.Body))
                        {
                            using (var jsonTextReader = new JsonTextReader(sr))
                            {
                                request = Serializer.Deserialize <AbpGraphQLRequest>(jsonTextReader);
                            }
                        }
                    }
                    else if (mediaType.IsSubsetOf(GraphQLMediaType))
                    {
                        request = new AbpGraphQLRequest();

                        using (var sr = new StreamReader(context.Request.Body))
                        {
                            request.Query = await sr.ReadToEndAsync();
                        }
                    }
                    else if (context.Request.Query.ContainsKey("query"))
                    {
                        request = new AbpGraphQLRequest
                        {
                            Query = context.Request.Query["query"]
                        };


                        if (context.Request.Query.ContainsKey("variables"))
                        {
                            request.Variables = JObject.Parse(context.Request.Query["variables"]);
                        }

                        if (context.Request.Query.ContainsKey("operationName"))
                        {
                            request.OperationName = context.Request.Query["operationName"];
                        }
                    }
                }
                catch (Exception e)
                {
                    await WriteErrorAsync(context, "An error occured while processing the GraphQL query", e);

                    return;
                }
            }
            else if (HttpMethods.IsGet(context.Request.Method))
            {
                if (!context.Request.Query.ContainsKey("query"))
                {
                    await WriteErrorAsync(context, "The 'query' query string parameter is missing");

                    return;
                }

                request = new AbpGraphQLRequest
                {
                    Query = context.Request.Query["query"]
                };
            }

            var queryToExecute = request.Query;

            if (!string.IsNullOrEmpty(request.NamedQuery))
            {
                var namedQueries = context.RequestServices.GetServices <INamedQueryProvider>();

                var queries = namedQueries
                              .SelectMany(dict => dict.Resolve())
                              .ToDictionary(pair => pair.Key, pair => pair.Value);

                queryToExecute = queries[request.NamedQuery];
            }

            var result = await _executor.ExecuteAsync(_ =>
            {
                _.Schema        = schema;
                _.Query         = queryToExecute;
                _.OperationName = request.OperationName;
                _.Inputs        = request.Variables.ToInputs();
                _.UserContext   = _options.BuildUserContext?.Invoke(context);

#if DEBUG
                _.ExposeExceptions = true;
#endif
            });

            var httpResult = result.Errors?.Count > 0
                ? HttpStatusCode.BadRequest
                : HttpStatusCode.OK;

            context.Response.StatusCode  = (int)httpResult;
            context.Response.ContentType = "application/json";

            await _writer.WriteAsync(context.Response.Body, result);
        }
Пример #2
0
        public async Task <IActionResult> PostAsync(GraphQLQuery query)
        //public async Task<IActionResult> PostAsync(System.Text.Json.JsonElement rawQuery)
        {
            //string rawJson = rawQuery.ToString();
            //var query = JsonConvert.DeserializeObject<GraphQLQuery>(rawJson);
            //query = System.Text.Json.JsonSerializer.Deserialize<GraphQLQuery>(rawJson);
            //Console.WriteLine(query.NamedQuery);
            //Console.WriteLine(query.OperationName);
            //Console.WriteLine(query.Query);
            //Console.WriteLine(query.Variables);

            //Dotnet 3.1 deserializes Dictionary<string,object> types into JsonElement values. We need the values as primitive types
            //TODO Create custom JSON converter
            query.Variables = query.Variables.ToDictionary(x => x.Key,
                                                           x =>
            {
                if (x.Value is JsonElement element)
                {
                    //TODO Handle more types and safely
                    switch (element.ValueKind)
                    {
                    case JsonValueKind.Number:
                        return(element.GetInt32());
                    }
                }

                return(x.Value);
            });


            Inputs inputs = null;

            if (query.Variables != null)
            {
                //var dictionary =
                //    System.Text
                //        .Json
                //        .JsonSerializer
                //        .Deserialize<Dictionary<string, object>>(
                //            query.Variables);
                inputs = new Inputs(query.Variables.ToDictionary(x => x.Key, x => (object)x.Value));
                //inputs = new Inputs(query.Variables);
            }


            var schema = _schemaFactory.GetSchema(query);

            var result = await new DocumentExecuter().ExecuteAsync(options =>
            {
                options.Schema        = schema;
                options.Query         = query.Query;
                options.OperationName = query.OperationName;
                options.Inputs        = inputs;
                //options.Inputs = new Inputs(new Dictionary<string, object> {{"id", 1}});
            });

            if (result.Errors?.Count > 0)
            {
                return(BadRequest(result.Errors));
            }

            return(Ok(result.Data));
        }