4

I developed a .net core 3.1 web API and I've added GraphQL and PlayGround to it. When I try to start the Playground I encountered this error that bored me. I googled too many times and I have read many articles and forums about it and I've tried their suggested ways but still, the problem exists. Also, I should say I haven't this problem with .net core 2.2.

I decided to simplify my solution and remove the extra foliage of my project and upload it to you that you can help me. The simplified version of that project I'm currently working on it is available here on google drive.
Also, I found a solution with .net core 3.1 that hasn't this problem but still, I can't find my mistake(s). I've uploaded this correct solution here.

In this simplified version I didn't connect to the database and didn't add any related of its packages to the project. I'm returning in-memory data in this simplified version instead of contacting the database.

This is the picture of the error that I'm facing: enter image description here

And The .csproj file of the simplified project is like below:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RootNamespace>NetCore3._1GraphQL</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="graphiql" Version="1.2.0" />
    <PackageReference Include="GraphQL" Version="3.0.0-preview-1352" />
    <PackageReference Include="GraphQL.Server.Ui.Playground" Version="3.4.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
    <PackageReference Include="RandomNameGeneratorLibrary" Version="1.2.2" />
  </ItemGroup>

</Project>
Milad Rashidi
  • 1,296
  • 4
  • 22
  • 40

2 Answers2

1

Depending on the simplified and erroneous project, afaict, it is configured with a routing which maps /graphql endpoint to a controller but does not contain a matching controller. So, the server returns 404 response and graphql playground produces error message. Adding a controller (or a middleware) made it work.

Below are the changes to the simplified and erroneous project that made it work:

  1. Add an api controller matching /graphql routing.
// GraphqlController.cs
// using statements are omitted
namespace NetCore3._1GraphQL.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class GraphqlController : ControllerBase
    {
        private readonly IServiceProvider _provider; 
        private readonly IDocumentExecuter _executer;
        private readonly IDataLoaderContextAccessor _loader;

        public GraphqlController(
            IDocumentExecuter executer,
            IServiceProvider provider, 
            IDataLoaderContextAccessor loader)
        {
            _executer = executer;
            _provider = provider;
            _loader = loader;
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody] GraphQLRequest graphQLRequest)
        {
            if (graphQLRequest == null)
            {
                throw new ArgumentNullException(nameof(graphQLRequest));
            }

            var _query = graphQLRequest.Query;
            var _inputs = graphQLRequest.Variables?.ToObject<Inputs>();
            var _options = new ExecutionOptions
            {
                Schema = new GraphQLSchema(_provider)
                {
                    Query = new GraphQLQuery(_loader),
                },
                Query = _query,
                Inputs = _inputs,
                FieldNameConverter = new PascalCaseFieldNameConverter()
            };

            try
            {
                var result = await _executer.ExecuteAsync(_options).ConfigureAwait(false);

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

                return Ok(result);
            }
            catch (Exception ex)
            {
                return BadRequest(ex);
            }
        }
    }
}

  1. Uncomment the line public JObject Variables { get; set; } in BaseGraphQLQuery.cs.

  2. BaseGraphQLQuery class is an implementation of a GraphQL request, not a GraphQL query. Rename it as GraphQLRequest or change the parameter name in the controller's post action to BaseGraphQLQuery.

A successfull query with Graphql Playground app.

moustapha
  • 71
  • 1
  • 5
  • Thank you @moustapha. I am very busy right now, but I will check your answer as soon as possible. – Milad Rashidi Jan 11 '21 at 06:21
  • I checked your answer and you were right. A year ago, when I downloaded this project from the Internet, I was a beginner in GraphQL and did not know that there must be a controller to handle GraphQL requests. But let's add this point to your answer to make it better for other readers of this question. Change line 76 where the app used the GraphQLPlayground tool like this: `app.UseGraphQLPlayground(options: new GraphQLPlaygroundOptions() { Path = "/graphqlplayground", GraphQLEndPoint = "/graphql" });` and the PlayGround will appear at this https://localhost:44313/graphqlplayground – Milad Rashidi Feb 12 '21 at 15:19
  • Do you have a working .net core controller app which is using Graphql.net 4? – killjoy Mar 03 '22 at 18:43
  • @killjoy, sorry, I don't have one at the moment. Please have a look at the [graphql-dotnet examples](https://github.com/graphql-dotnet/examples). If you have an issue please provide the details so we can help. – moustapha Mar 23 '22 at 09:29
0

add in the startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        //add this
        services.AddSingleton<MyAppSchema>();
    }