HotChocolate: Introduction to GraphQL for ASP.NET Core (Part 1)
John Ojo
Posted on January 4, 2021
In this post, I will walk you through how to get started with GraphQL in ASP.NET Core using HotChocolate.
In this part, we will only focus on GraphQL Server, configuring it with ASP.NET Core.
In part 2, We will focus on integrating the GraphQL endpoint into a Blazor WebAssembly application.
Introduction
GraphQL 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. It lets you specify exactly what data you need.
HotChocolate is a .NET GraphQL platform that can help you build a GraphQL layer over your existing and new application. HotChocolate is very easy to set up and takes the clutter away from writing GraphQL schemas.
We will create a simple application that can be used to Create, Read, Update and Delete an Employee together with a department.
The code for this sample can be found on the CloudBloq/GraphQLSampleApp repository on GitHub.
Prerequisites
The Database
The database schema and data script can be found in the folder CloudBloq/GraphQLSampleApp/tree/master/GraphQLSampleApp/Script. Ensure to run the script in SQL Server Management Studio or in Visual Studio SQL Server Object Explore to set up the Database and tables.
Create the Solution and Project
We will need an ASP.NET Web API project. After opening VS, click the Create a new project link and select the ASP.NET Core Web Application, give the project a name GraphQLSampleApp and the solution a name GraphQLSampleApp click Create. Next, select the API, then click Create.
Install Dependencies
We need to install the HotChocolate.AspNetCore(v11.0.2) package. The package contains the GraphQL API's for ASP.NET. To install the package, right click the solution in the solution explorer and select Manage NuGet Packages for Solution. Under the Browse section, search for HotChocolate.AspNetCore and click on it, then in the preview panel click the Install button:
Also, install the Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools packages respectively.
The Entities
We will make use of EntityFrameworkCore as the ORM. Entities (classes) are used to define the database objects (tables) and those entities are mapped to the database table in the DbContext.
We will define two Entities, one for the Department and the other for the Employee tables.
We will keep everything simple by using folders to hold the data access code, the GraphQL code and the Database Entities. In a real application, a Class library would be better for the different layers.
Create a folder called DataAccess in the GraphQLSampleApp project, create another folder called Entity inside the DataAccess folder.
Department Entity
Add a C# Class file called Department.cs to the Entity folder. This class will be used to define the Department entity. The code for this file is:
Line 9 is used to mark the DepartmentId property as the primary key of the entity, line 10 is used to ensure that the value of the DepartmentId is unique and auto generated if it is not provided by the user. Line 15 is used to define a relationship (navigation property) between the Department and Employee entity. The relationship:
public ICollection<Employee> Employees { get; set; }
means that a single Department can have many Employees assigned to it. This line will throw an error now unless you have created the Employee entity earlier.
Employee Entity
Add another C# class to the Entity folder called Employee.cs. After adding this class, the error gotten earlier in Department.cs will no longer be there. The code for this file is:
Line 24 defines the foreign key property used to link an Employee to his/her department. Line 25 defines the navigation property that states that an Employee can only have one department.
The DbContext
The DbContext will be simple and straight forward. In a real application, most of the database configurations are done in this file. Add a new C# Class file to the Entity folder, name it SampleAppDbContext.cs. The code for this file is:
Line 11 defines the Employee property which is used to map the Employee.cs entity to the Employee table in the database. Line 13 defines the Department property which is used to map the Department.cs entity to the Department table in the database.
Repositories
Next, we will write the layer that will send and receive data to and from the database. In the DataAccess folder, add another folder called DAO.
Department Repository
Add a C# class file called DepartmentRepository.cs to the DAO folder:
Lines 19 to 22 define the GetAllDepartmentOnly() method which is used to return a list of all the Departments.
Lines 24 to 29 define the GetAllDepartmentsWithEmployee() method which returns all the Departments along-side the Employee(s) in each Department. The navigation property defined in line 15 in Department.cs made it possible to return the Departments along-side the Employee(s).
Lines 31 to 36 define the CreateDepartment() method which takes in a new Department and adds it to the database.
Employee Repository
Add a C# class file called EmployeeRepository.cs to the DAO folder:
This class defines the GetEmployees() which returns a list of all the Employees, the GetEmployeeById() which takes an Id and returns the Employee only if the Id is valid and exists, the GetEmployeesWithDepartment() which returns a list of all the Employees along-side the Department, and the CreateEmployee() which takes in an Employee and adds them to the database.
GraphQL
If you are familiar with REST API, we use GET to fetch data from the data store, we use POST, PUT DELETE to modify the state of data. GET in REST API is same as Query in GraphQL. POST, PUT, DELETE, is same as Mutation. In GraphQL, there is also Subscription which is used to set up event listeners.
Query
Add a new C# class file called Query.cs to the DataAccess folder. This class will contain all the Queries we need to perform:
AllEmployeeOnly() on line 12 returns all the Employees; we inject an instance of the EmployeeRepository into this method by marking the input parameter with the [Service] attribute. AllEmployeeWithDepartment() on line 15 returns the Employees along-side the Department.
Line 18 defines GetEmployeeById(), the parameter ITopicEventSender eventSender is used to create a subscription with Topic "ReturnedEmployee". Anytime this method is called, the event is sent on line 22 and any method that subscribes to this event will receive the data.
Mutation
Add a new C# class file called Mutation.cs to the DataAccess folder. This class will contain all the Mutations we need to perform:
Line 15 defines CreateDepartment(). The parameter departmentName will be provided by the user. The parameter ITopicEventSender eventSender is used to create a subscription with Topic "DepartmentCreated".
Line 29 defines a method CreateEmployeeWithDepartmentId() that can be used to create a new Employee passing in an existing DepartmentId i.e. create an Employee with an existing department. The parameters name: string, age: int, email: string, and departmentId: int will be provided by the user. Notice we set the DepartmentId on line 37 to the departmentId passed by the user.
Line 44 defines CreateEmployeeWithDepartment(). This method is used to create a new Employee. In the process of creating the Employee, a new Department is created and the DepartmentId property of this Employee is set automatically to the DepartmentId of the newly created Department. Notice how this is done on line 52 by setting the navigation property to a new Department.
Subscription
Subscriptions are used to set up event listeners e.g. we can set up an event listener that responds when we create a new Department or Query the database for an Employee etc. Add a new C# class file called Subscription.cs to the DataAccess folder:
OnDepartmentCreate() on line 17 defines a subscriber of Topic "DepartmentCreated" likewise line 25 defines OnEmployeeGet() a subscriber of Topic "ReturnedEmployee".
Configuring GraphQL
We need to configure the application to make use of GraphQL. Replace the code in your Startup.cs with:
Line 32 is used to add the Service for GraphQL, Query, Mutation and Subscription. The AddQueryType(), AddMutationType() and AddSubscriptionType() takes in the Query, Mutation and Subscription classes respectively.
Line 55 is used to map the endpoint to use GraphQL.
The middleware on line 50 is used to configure the application to ensure the Subscription gives the output.
Line 27 adds the DbContext service; we configure this service to make use of SQL Server as the database. The connection string is defined in the appsettings.json file as:
Don't forget to change the Data Source value to that of the database you ran the schema and data script in.
Running the Application
Right-click the solution and click Build Solution. After Build is successful, click CTRL + f5 or f5 to run the application. In your browser, navigate to https://localhost:44351/graphql/, you should get
HotChocolate gives you a GraphQL IDE (Banana Cake Pop) right in your browser out of the box, you don't need to install any GraphQL IDE.
The methods defined in Query.cs, Mutation.cs and Subscription.cs have been categorized under Query, Mutation and Subscription respectively.
Test Query
In Banana cake pop, you can add a new tab by clicking the + in the top right corner of the IDE. You can run your schema by clicking the Execute/Play button in the top right corner. Add and run:
query{
allDepartmentsWithEmployee{
name
employees{
email
name
}
}
}
You should get the response in the image below:
.
Try out other Query types, defining the Schema of the data you need.
Test Subscription and Query
Add and run the schema below:
subscription{
onEmployeeGet{
name
departmentId
department{
name
}
}
}
This Subscribes to the event "ReturnedEmployee" in line 28 of Subscription.cs. You won't get any output yet as shown in the image above, but you can see from the console that we have Subscribed to the event.
Launch https://localhost:44351/graphql/ in another browser tab. Next, we will run a Query that will trigger the event. Add and run the below in a new Banana Cake Pop tab in the new browser tab:
query{
employeeById(id: 5){
name
email
}
}
If you go back to the first browser tab where we subscribed to the event, you will get the response
If you change the value of the id and run the Query, you will see the changes in the Subscription.
Test Mutation
Add and run the schema below:
mutation{
createEmployeeWithDepartment(name: "newemp", age: 30,
email: "newemp@gmail.com", departmentName: "Mechanical Engr"){
departmentId
name
department{
departmentId
name
}
}
}
You would get
Whoa! We have come to the end of this tutorial. I only added the functions to Create and get an Employee and Department. You are free to explore more and add more functions.
Awesome! Please share it with anyone you think could use this information. Thanks for reading. As always, if you have any questions, comments, or concerns about this post, feel free to leave a comment below.
Reference
Posted on January 4, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.