Hi
I was wondering if it is possible to stitch schemas entirely in code as I currently have a graphql-dotnet implementation running but I want to start using hotchocolate, and I want it in the same API, I dont want to spin up a new api for hotchocolate and then a third to stitch them together. Is it possible?
Cheers
Yes, that is possible ... you can have in memory schemas and stitch them together.
Okay, thanks for the answer!
Do you have any example code to show how it might be done?
This leads me to the next question, how do you get hotchocolate to pass on resolution of all the fields to the graphql-dotnet implementation?
So for GraphQL-DotNet you need to provide as access to their document executor ... you basically implement our executor interface and pass the requests on.
@PascalSenn how did you guys do that? Did you have different hosts? Or did you do it in-place?
@michaelstaib this is what is currently being set up by @OneCyrus
we built an inmemory http message handler for the httpclient factory which executes graphql-dotnet requests. similar how the asp.net core testhost works. can post some code later.
so here's some code. it's simplified from our own use case but that should you get there.
https://gist.github.com/OneCyrus/32c85317b9c72aa52cc50c446b0f8253
Thanks, @OneCyrus for providing the info. I will close this issue now.
Thanks @OneCyrus and @michaelstaib, looks like what I need, Ill be taking a closer look on Monday, tomorrow.
Cheers
Hi there @OneCyrus, I cannot call the services.BuildServiceProvider() within the Startup.ConfigureServices method as it would start up a lot of services, singletons etc before they are properly configured in the Startup.Configure step. And I cannot see any easy way to resolve the GraphQL.Types.ISchema within hot chocolate's setup.

you don't need to generate the schema on startup. you can use something like this with a static schema file.
var sdl = Path.Combine(HostingEnvironment.ContentRootPath, "MySDL.graphql");
services.AddStitchedSchema(builder => builder
.AddSchemaFromFile("sdl", sdl )
we are using a similiar approach as well as we have a schema registry where all the schemas from our microservices are located. the downside is just that you need to send/export the schema each time you update something in the service. but you could use a unit test which simplifies this.
I have a json file with the schema, do yo guys have any utilities to convert it to gql - sdl?
with schema you mean an introspection response?
yeah, sorry for not being clear on that
I'm not aware of a converter utility from introspection to SDL. how do you generate the introspection? is there no way you could generate a SDL as well?
yeah what I do now is introspect the old api endpoint with graphql playground, copy the sdl to a schema.gql file in the same project, load it when the api starts up and stitches it into the hot chocolate's scheam and endpoint, which is a very cumbersome and manual job 😅.
that's how you could export a SDL as part of a unit test
public class AuthIntegrationTests : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _authTestFactory;
public AuthIntegrationTests(WebApplicationFactory<Startup> authFixture)
{
_authTestFactory = authFixture;
}
[Fact]
public async Task ExportGraphql_Schema()
{
var schema = _authTestFactory.Services.GetService<GraphQL.Types.ISchema>();
var sdl = new SchemaPrinter(schema).Print();
var snapshotPath = (new XunitSnapshotFullNameReader()).ReadSnapshotFullName();
sdl.MatchSnapshot("MySDL");
}
}
Thanks @OneCyrus ill take a look, in the meantime I have managed to fix some issues and inconsistencies we had in our old schema where some interfaces and types implementing those had fields which did not match return types etc.
Now the AddSchemaFromString runs without errors but the introspection result from the hot chocolate endpoint does not contain the stitched schema, it's as if I never stitched anything.
services.AddHttpClient(
"graphqldotnet",
(sp, client) =>
{
client.BaseAddress = new Uri("http://notactuallycalled/graphql");
}
).ConfigurePrimaryHttpMessageHandler(sp => new GraphQLDotNetMessageHandler(sp));
services
.AddStitchedSchema(builder => builder.AddSchemaFromString("graphqldotnet", File.ReadAllText("schema.gql", Encoding.UTF8)))
.AddDataLoaderRegistry()
.AddGraphQL(
sp => SchemaBuilder.New()
.AddQueryType<RootQuery>()
.AddMutationType<RootMutation>()
.Create(),
new QueryExecutionOptions
{
ForceSerialExecution = true,
IncludeExceptionDetails = !HostingEnvironment.IsProduction()
}
)
.AddQueryRequestInterceptor(
(ctx, builder, ct) =>
{
// TODO
return Task.CompletedTask;
}
);
I have verified that File.ReadAllText("schema.gql", Encoding.UTF8) in deed returns the sdl for the existing graphql impl.
The configuration looks wrong ... You have to integrate everything with the stitching builder.
Clearly something I am misunderstanding here, could you clarify please?
Cheers
just for completion I am posting the basic code I ended up with for supporting this.
services.AddHttpClient(
"graphqldotnet",
(sp, client) =>
{
client.BaseAddress = new Uri("http://notactuallycalled/graphql");
}
).ConfigurePrimaryHttpMessageHandler(sp => new GraphQLDotNetMessageHandler(sp));
services
.AddDataLoaderRegistry()
.AddStitchedSchema(
builder => builder
.AddSchemaFromString(
"graphqldotnet",
File.ReadAllText("schema.gql")
)
.AddSchema(
"hotchocolate",
SchemaBuilder
.New()
.AddQueryType<RootQuery>()
.AddMutationType<RootMutation>()
.Create()
)
.AddSchemaConfiguration(
config =>
{
config.RegisterExtendedScalarTypes();
}
)
)
.AddQueryRequestInterceptor(
(context, builder, cancellationToken) =>
{
if (context.User.Identity.IsAuthenticated)
{
builder.SetProperty("UserId", context.User.GetUserId());
}
return Task.CompletedTask;
}
);
Most helpful comment
so here's some code. it's simplified from our own use case but that should you get there.
https://gist.github.com/OneCyrus/32c85317b9c72aa52cc50c446b0f8253