GraphQL over .Net classes realization.
- Build GraphQL project and understand the meaning of mandatory GraphQL over .Net classes
- Query single book by id parameter
- Queries (book and author getById/getAll)
- Mutations (book and author operations: create/update/delete)
- Subscription with book's title update event
- Variables support
- Organized schema
- Author's books in model (and book's author)
- A bit of business logic + graphql exception handler
- GraphQL Client
- Unit/Integration tests
- Add DataLoader
Run the project, Altair UI is on https://localhost:5001/ui/altair
Available schemas on right side of a screen.
- Create web project
- Add necessary GraphQL nuget packages
<PackageReference Include="GraphQL" Version="7.1.1" /> <PackageReference Include="GraphQL.MicrosoftDI" Version="7.1.1" /> <PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="7.1.1" /> <PackageReference Include="GraphQL.Server.Ui.Altair" Version="7.1.1" /> <PackageReference Include="GraphQL.SystemTextJson" Version="7.1.1" />
- Configure services
services.AddGraphQL(b => b .AddSystemTextJson() .AddDocumentExecuter<DocumentExecuter>() .AddGraphTypes() .AddSchema<StoreSchema>() .AddComplexityAnalyzer(opt => { #if !DEBUG opt.MaxComplexity = 200; #endif }) ); })
- Configure GraphQL web app (Middleware + UI)
builder.UseGraphQLAltair(); builder.UseMiddleware<GraphQLMiddleware>();
- Add root Schema, Mutation and Query to project
- Schema <= Query/Mutation <= Field (Namespace) <= Type <= GroupType <= Type
- Create library project
- Add required nuget packages for GraphQL client project
<PackageReference Include="GraphQL.Client" Version="5.1.0" />
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="5.1.0" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.1.1" />
- Implement GraphQL client by
GraphQLHttpClient
(look atGraphQLWebClientBase.cs
)
Operation | GraphQL | Rest |
---|---|---|
Read | Query | GET |
Write | Mutation | POST, PUT, PATCH, DELETE |
Events | Subscrition | N/A |
- HTTP POST most common for Query and Mutation
- HTTP GET often used for Query when using persisted queries
- WebSockets most common for Subscribtion
- gRPC used in some instances
- One endpoint, single request
- No over/under fetching
- Strong type system gives very predictable to use the API from user perspective
- GraphQL isnt tied to any specific database/storage engine
- Multiple subscriptions => Multiplexing (WS protocol by GraphQL solved this problem)
- Throttling => Batching (Mobile/web overflow by events)
There are two ways you can build your schema: Schema first approach using the GraphQL schema language AND the other one is GraphType or Code first approach by writing GraphType classes.
Using GraphQLMetadata to customize the mapping to the schema type.
The GraphType first approach gives you access to all of the provided properties of your GraphType's and Schema.
Complexity analyzer prevents malicious queries.
A DataLoader helps in two ways - improves data fetching and ensures consistency:
- Similar operations are batched together. This can make fetching data over a network much more efficient.
- Fetched values are cached so if they are requested again, the cached value is returned.
DocumentExecuter is a class which executes, validates, analyses the request by specified providers: ISchema, IDocumentBuilder, IDocumentValidator.
Subscription helps to track any changes by asynchronous data stream.
Rough data pipeline on sub: Event stream => Executer => Resolver => Response stream
- Full control over data
- Error boundaries => data quality
- @defer/@stream => prioritisation
- Stronger type system