Reputation: 4916
I was following a Plural Site course "Building GraphQL APIs with ASP.NET Core" but seem to have come unstuck. When running the "playground", the browser loads with:
{ "error": "Unexpected token S in JSON at position 0" }
If I run this as the application (so not IISExpress) then in the console window I see the following failure:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. System.InvalidOperationException: Synchronous operations are disallowed.
I found a few posts that said to add the AllowSynchronousIO
option, which I did but to no avail. I tried running in IISExpress too...no difference.
Here are some details of my setup:
.Net Core I created an ASP.NET Core 3.1 (3.1.6) Web API project.
NuGet packages
There is a disclaimer on the github site that the latest stable version has "many known issues" which have probably been fixed in a preview release, but I tried those and couldn't even get it to compile....
Startup.cs
Using statements
using global::GraphQL;
using global::GraphQL.Server;
using global::GraphQL.Server.Ui.Playground;
using global::GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WebApiGQL.GraphQL.Schema;
using WebApiGQL.Repository;
ConfigureServices
services.AddCors();
services.AddScoped<IProductRepository, ProductRepository>();
services.AddScoped<IDependencyResolver>(s => new FuncDependencyResolver(s.GetRequiredService));
services.AddScoped<ProductSchema>();
services
.AddGraphQL(o => { o.ExposeExceptions = true; })
.AddGraphTypes(ServiceLifetime.Scoped);
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Configure
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(o => o.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseGraphQL<ISchema>();
app.UseGraphQLPlayground(new GraphQLPlaygroundOptions());
[Note: the app.UseCors(...)
will eventually go into the if (env.IsDevelopment())
block.]
I tend not to develop Core apps in IISExpress because I think you get better diagnostics from the command window that pops up.
GraphQL looks so powerful, I'd love to get this up and running....but just can't see what I'm missing.
Edit 3rd Aug: response to Yongqing Yu
So this is a really "Hello World" application that does NOT use the Entity Framework. The eventual application (if we go this way) would pull data from a series of end-points (e.g. SQL, other APIs, etc, etc), merge that data together and then return the merged details.
ProductSchema.cs
public class ProductSchema : Schema
{
public ProductSchema(IDependencyResolver resolver) :
base(resolver)
{
Query = resolver.Resolve<ProductQuery>();
}
}
IProductRepository
public interface IProductRepository
{
List<Product> GetAll();
//List<Product> GetList(List<string> skus);
//Product Get(string sku);
}
My intention would be to only have the two methods that are commented out, however I went back to basics and just had a "GetAll" method in an attempt to fix this.
ProductRepository
public class ProductRepository : IProductRepository
{
public List<Product> GetAll()
{
return this.AllProducts;
}
//public List<Product> GetList(List<string> skus)
//{
// return this.AllProducts.Where(p => skus.Contains(p.Sku)).ToList();
//}
//public Product Get(string sku)
//{
// return this.AllProducts.FirstOrDefault(p => p.Sku.Equals(sku));
//}
private readonly List<Product> AllProducts = new List<Product>
{
new Product
{
Sku = "ABC12345"
},
new Product
{
Sku = "ABC12345"
}
}
}
ProductType.cs
public class ProductType : ObjectGraphType<Product>
{
public ProductType()
{
Field(p => p.Sku);
}
}
Product.cs I started off with this as a complex beast where the properties included:
But, to simplify things I cut this down to:
public class Product
{
public string Sku { get; set; }
}
Upvotes: 1
Views: 1055
Reputation: 4916
Finally....solved this.
I had:
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
But needed:
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Upvotes: 1