In this article, we are going to understand the implementation steps of GraphQL in .Net5 application using Hot Chocolate Library.
Startup.cs:(Configure Method)
GraphQL:
GraphQL is an open-source data query and manipulation language for APIs. It is a query language for your API and a server-side runtime for executing queries by using a type system you define for your data. GraphQL can be integrated into any framework like .Net, Java, NetsJS, etc and it isn't tied to any specific database or storage engine and instead backed by your existing code and data.
GraphQL caries two important operations:
- Query - fetching data
- Mutation - save or update.
Hot Chocolate GraphQL:
Hot Chocolate is an open-source GraphQL server that is compliant with the newest GraphQL latest specs. It is the wrapper library of the original .Net GraphQL library. Hot Chocolate takes the complexity away from building a fully-fledged GraphQL server.
An Overview On GrphQL SDL(Schema Definition Language):
A syntax to data query and manipulation in GraphQL called SDL(schema definition language). GraphQL SDL syntax looks similar to the javascript object. Hot Chocolate GraphQL library providers flexibility to develop GraphQL endpoint either using Schema First approach(purely uses GraphQL SDL syntax) or using Code First approach(in this approach framework will take responsibility of generating GraphQL SDL implicitly for dotnet developers this will be ideal approach). So this section is to get familiar with GraphQL SDL syntax for better understanding.
GraphQL SDL syntax to define 'type'(in c# class is equivalent to the GraphQL SDL 'type') object(in c# it is like our database table representing class).
type Book { Id: Int Name: String }
- Here we defined the 'Book' GraphQL SDL type object. Its properties are 'Id', 'Name'. Its properties types are like 'Int', 'String' are GraphQL scalar types.
type Query { book: Book }
- This 'Query type' is an entry point to fetch data. It contains all resolvers(means logic to fetch data).
- Here we define 'book: Book' means on requesting 'book' query we get a response of single object of type 'Book', similarly we need to define all fetch logic inside of the 'Query'.
type Mutation{ create(book:BookInput):Book }
- The 'Mutation type' contains all the logic for saving or updating the data.
- Here 'create(book: BookInput)' is the resolver method to save data.
type Schema{ query:Query, mutaition:Mutation }
- Schema is the root type in GraphQL where 'Query' and 'Mutations' registered.
Create A .Net5 Web API Application:
Let's create a .Net5 Web API application in which we are going to integrate GraphQL. For development, any IDE can be used but most preferred are Visual Studio 2019(Version 16.8.* that supports .Net5) or Visual Studio Code.
Hot Chocolate Library:
Package Manager Command:
Install-Package HotChocolate.AspNetCore -Version 11.0.2
.Net CLI Command:
dotnet add package HotChocolate.AspNetCore -Version 11.0.2
Register GraphQL Service And Endpoint:
First we need to register our GraphQL service that is 'AddGraphQLServer()'. This 'AddGraphQLServer()' extension method enables schema and executor.
Startup.cs:(ConfigureServices Method)
services.AddGraphQLServer();Now configure GraphQL endpoint.
Startup.cs:(Configure Method)
app.UseEndpoints(endpoints => { endpoints.MapGraphQL(); endpoints.MapControllers(); });
POCO Class And GraphQL ObjectType:
A plain class is a general used to represent a table for fetching the data in .Net application. So lets create a POCO(Plain Old CLR Object) class that will type for our data return form the server.
Data/Entities/Gadgets.cs:
namespace HC.GraphQL.Sample.Data.Entities { public class Gadgets { public int Id { get; set; } public string ProductName { get; set; } public string Brand { get; set; } public decimal Cost { get; set; } public string Type { get; set; } } }Now GraphQL doesn't understand our 'Gadget.cs' .net class because GraphQL can only understand SDL syntax. So to make our POCO class understand by GraphQL we need to map it with 'HotChocolate.Types.ObjectType'. In this 'ObjectType' we need to register all our POCO class properties so that on runtime 'ObjecType' generates GraphQL SDL type which is understandable by the GraphQL execution schema.
So let's create a 'HotChocolate.Types.ObjectType' for our 'Gadget' class.
ObjectTypes/GadgetsObjectType.cs:
using HC.GraphQL.Sample.Data.Entities; using HotChocolate.Types; namespace HC.GraphQL.Sample.ObjectTypes { public class GadgetsObjectType : ObjectType<Gadgets> { protected override void Configure(IObjectTypeDescriptor<Gadgets> descriptor) { descriptor.Field(g => g.Id).Type<IntType>().Name("Id"); descriptor.Field(g => g.ProductName).Type<StringType>().Name("ProductName"); descriptor.Field(g => g.Brand).Type<StringType>().Name("Brand"); descriptor.Field(g => g.Cost).Type<DecimalType>().Name("Cost"); descriptor.Field(g => g.Type).Type<StringType>().Name("Type"); } } }
- Here we create 'GadgetsObjectType' that inherits 'HotChocolate.Types.ObjectType<Gadgets>'.
- Inside the 'Configure' method we are registering the properties of 'Gadget' classes as the 'Field' to the ObjectType.
- Here 'IntType','StringType','DecimalType' are scalar types provided by the HotChocolate GraphQL library.
- The 'Name()' extension method to define the name of each 'Field' registered.
type Gadgets{ Id: Int, ProductName: String, Brand:String, .... }
Create Query And Its ObjectType:
In GraphQL 'Query' type is the entry point for fetching the data. So let's create our query class.
SchemaCore/Query.cs:
using HC.GraphQL.Sample.Data.Entities; namespace HC.GraphQL.Sample.SchemaCore { public class Query { public Gadgets FirstGadget() { return new Gadgets{ Id = 1, ProductName = "Samsung M30s", Brand = "Samsung", Cost = 15000, Type = "Mobile" }; } } }
- Here 'FirstGadget()' method is our resolver method where we fetching a single record.
ObjectTypes/QueryObjectType.cs:
using HC.GraphQL.Sample.SchemaCore; using HotChocolate.Types; namespace HC.GraphQL.Sample.ObjectTypes { public class QueryObjectType:ObjectType<Query> { protected override void Configure(IObjectTypeDescriptor<Query> descriptor) { descriptor.Field(g => g.FirstGadget()) .Type<GadgetsObjectType>().Name("FirstGadget"); } } }
- Here we registered our resolver method 'FirsGadget()' as a field for QueryObjectType.
- Defined its 'Type' as 'GadgetsObjectType'(This GadgetObjectType represents our c# gadget class for GraphQL).
- The 'Name' extension method defines the name for the field.
type Query{ FirstGadget: Gadgets }
Register Query:
Now we need to register our 'QueryObjectType' in the Startup file
Startup.cs:(ConfigureServices Method)
services.AddGraphQLServer() .AddQueryType<QueryObjectType>();
Fields:
GraphQL is about asking for specific fields on objects on the server. Let's test API by requesting Fields.
Request Query:
query{ FirstGadget{ Brand ProductName } }
- Here 'query' to invoke the 'QueryObjectType'. The name 'FirstGadget' should match with the registered name in 'QueryObjectType' so this will invoke the specific resolver method on our server-side. In the above request, we are asking the server only to send 2 properties.
Create A Resolver Method To Fetch Multiple Records:
Now let's add a new resolver method in the 'Query' class that returns multiple records.
SchemaCore/Query.cs:
public List<Gadgets> AllGadgets() { return new List<Gadgets> { new Gadgets{ Id = 1, ProductName = "Samsung M30s", Brand = "Samsung", Cost = 15000, Type = "Mobile" }, new Gadgets{ Id = 2, ProductName = "Think Pad", Brand = "Lenovo", Cost = 75000, Type = "Laptop" } }; }Now register this 'AllGadgets' resolver method as a field in the 'QueryObjectType'.
ObjectTypes/QueryObjectType.cs:
descriptor.Field(g => g.AllGadgets()) .Type<ListType<GadgetsObjectType>>().Name("AllGadgets");
- Here 'ListType' GraphQL type that is equivalent to 'List'
Support Me!
Buy Me A Coffee
PayPal Me
Wrapping Up:
Hopefully, I think this article delivered some useful information on implementing Hot Chocolate GraphQL in .Net5 Application. I love to have your feedback, suggestions, and better techniques in the comment section below.
Hi Naveen, I've implemented a few graphql servers in dotnet, but I have always had trouble consuming it from a client i.e an app or website and I'd be interested to hear if you'd do a chapter exclusively on actually consuming it, ideally using Blazor
ReplyDeleteMany thanks,
Mani
Hi Mani
DeleteI made blog using angular
https://www.learmoreseekmore.com/2021/03/angular-application-consume-graphql-endpoint-using-apollo-angular-library.html
I tried using blazor library like Strawberry Shake(Hot Chocolate GraphQL library)
but currently i'm facing some issue with it.