Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Web API Development with ASP.NET Core 8

You're reading from  Web API Development with ASP.NET Core 8

Product type Book
Published in Apr 2024
Publisher Packt
ISBN-13 9781804610954
Pages 804 pages
Edition 1st Edition
Languages
Author (1):
Xiaodi Yan Xiaodi Yan
Profile icon Xiaodi Yan

Table of Contents (20) Chapters

Preface 1. Chapter 1: Fundamentals of Web APIs 2. Chapter 2: Getting Started with ASP.NET Core Web APIs 3. Chapter 3: ASP.NET Core Fundamentals (Part 1) 4. Chapter 4: ASP.NET Core Fundamentals (Part 2) 5. Chapter 5: Data Access in ASP.NET Core (Part 1: Entity Framework Core Fundamentals) 6. Chapter 6: Data Access in ASP.NET Core (Part 2 – Entity Relationships) 7. Chapter 7: Data Access in ASP.NET Core (Part 3: Tips) 8. Chapter 8: Security and Identity in ASP.NET Core 9. Chapter 9: Testing in ASP.NET Core (Part 1 – Unit Testing) 10. Chapter 10: Testing in ASP.NET Core (Part 2 – Integration Testing) 11. Chapter 11: Getting Started with gRPC 12. Chapter 12: Getting Started with GraphQL 13. Chapter 13: Getting Started with SignalR 14. Chapter 14: CI/CD for ASP.NET Core Using Azure Pipelines and GitHub Actions 15. Chapter 15: ASP.NET Core Web API Common Practices 16. Chapter 16: Error Handling, Monitoring, and Observability 17. Chapter 17: Cloud-Native Patterns 18. Index 19. Other Books You May Enjoy

Getting Started with GraphQL

In Chapter 11, we explored how to create a gRPC service in ASP.NET Core. gRPC is a high-performance RPC framework that facilitates communication between services. We discussed the field types used in protobuf messages, and how to define four types of gRPC services: unary, server streaming, client streaming, and bidirectional streaming. Additionally, we learned how to configure gRPC services in ASP.NET Core and how to call gRPC services from a client application.

Next, we will explore another shape of web APIs: GraphQL. GraphQL is a query-based API that allows clients to specify the data they need, which solves the problem of over-fetching and under-fetching data. Besides, GraphQL supports mutations, which allow clients to modify data. In this chapter, we will learn about some basic concepts of GraphQL and how to create a GraphQL API in ASP.NET Core. We will cover the following topics in this chapter:

  • Recap of GraphQL
  • Setting up a GraphQL...

Technical requirements

The code examples in this chapter can be found at https://github.com/PacktPublishing/Web-API-Development-with-ASP.NET-Core-8/tree/main/samples/chapter12. You can use VS 2022 or VS Code to open the solutions.

Recap of GraphQL

GraphQL offers a flexible way to query and mutate data. The main difference between GraphQL and REST is that GraphQL allows clients to specify the data they need, whereas REST APIs return a fixed set of data. GraphQL treats data as a graph, and it uses a query language to define the shape of the data. This addresses the issues of over-fetching and under-fetching data by enabling clients to specify their data requirements. Additionally, it supports mutations, empowering clients to modify data as needed.

While REST APIs have multiple endpoints for different resources, GraphQL is typically served over a single endpoint, usually /graphql, which exposes a schema that describes the data. All queries and mutations are sent to this endpoint. The schema is defined using a GraphQL Schema Definition Language, which is the contract between the client and the server. The schema defines the types of data and the operations that can be performed on the data. The client can use...

Setting up a GraphQL API using HotChocolate

To begin with, you can download the code example named SchoolManagement for this chapter from the chapter12\start folder. This sample project has some basic code for an AppDbContext class and a Teacher class, as well as some seed data. The Teacher class has the following properties:

public class Teacher{
    public Guid Id { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string? Phone { get; set; }
    public string? Bio { get; set; }
}

You can open the project in VS Code or VS 2022. We will integrate HotChocolate into the project to create a GraphQL API following these steps:

  1. Add the HotChocolate.AspNetCore NuGet package to the project. This package contains the ASP...

Adding mutations

In the previous section, we learned how to create a GraphQL API using HotChocolate. We added a query root type to query data. In this section, we will discuss how to modify data using mutations.

Mutations are used to modify data in GraphQL. A mutation consists of three parts:

  • Input: The input is the data that will be used to modify the data. It is named with the Input suffix following the convention, such as AddTeacherInput.
  • Payload: The payload is the data that will be returned after the mutation is executed. It is named with the Payload suffix following the convention, such as AddTeacherPayload.
  • Mutation: The mutation is the operation that will be executed. It is named as verb + noun following the convention, such as AddTeacherAsync.

Let us add a mutation to create a new teacher. We will use the following steps:

  1. Create an AddTeacherInput class in the GraphQL/Mutations folder, as shown here:
    public record AddTeacherInput(  ...

Using variables in queries

In the previous section, we learned how to query data and modify data using GraphQL queries and mutations. In this section, we will discuss how to use variables in queries.

GraphQL allows you to use variables in queries. This is useful when you want to pass parameters to the query. We can create a query that accepts an id parameter and returns the teacher with the specified ID. Follow these steps to create the query:

  1. Add a GetTeacher() method in the Query class, as follows:
    public async Task<Teacher?> GetTeacher(Guid id, [Service] AppDbContext context) =>    await context.Teachers.FindAsync(id);

    The preceding code adds a GetTeacher() method to the Query class. It takes an id parameter and returns the teacher with the specified ID.

  2. Now, you can use the $ sign to define a variable in the query. For example, you can use the following query to get a teacher by ID:
    query getTeacher($id: UUID!) {  teacher(id: $id...

Defining a GraphQL schema

Usually, a system has multiple types of data. For example, a school management system has teachers, students, departments, and courses. A department has multiple courses, and a course has multiple students. A teacher can teach multiple courses, and a course can be taught by multiple teachers as well. In this section, we will discuss how to define a GraphQL schema with multiple types of data.

Scalar types

Scalar types are the primitive types in GraphQL. The following table lists the scalar types in GraphQL:

Retrieving related objects using resolvers

In the previous section, we defined a Teacher type and a Department type. The Teacher type has a Department property of the Department type. When querying the Teacher object, we may also want to retrieve the Department object. How can we do that?

You may think that we can use the Include() method to retrieve the Department object, as follows:

public async Task<List<Teacher>> GetTeachers([Service] AppDbContext context) =>    await context.Teachers.Include(x => x.Department).ToListAsync();

Then, you can query the Department object as follows:

query{  teachers{
    id
    firstName
    lastName
    department{
      id
      name
      description
    }
  }
}

It does work and you will...

Using data loaders

In the previous section, we learned how to integrate HotChocolate with EF Core. We also learned how to use the DbContextPool feature to fetch data in multiple resolvers. However, we found that there are many database queries for each Department object in the Teacher list. That is because the resolvers for each Department object are executed separately, querying the database by each DepartmentId property in the list. This is similar to the N+1 problem we discussed in Chapter 1. The difference is that the N+1 problem occurs on the client side in REST APIs, while it occurs on the server side in GraphQL. To solve this problem, we need to find a way to load the batch data efficiently.

HotChocolate provides a DataLoader mechanism to solve the N+1 problem. The data loader fetches data in batches from the data source. Then, the resolver can retrieve the data from the data loader, rather than querying the data source directly. The data loader will cache the data for the...

Dependency injection

In the previous code examples, we use IDbContextFactory<AppDbContext> and AppDbContext directly in the resolvers. In order to encapsulate our data access logic, we can add a service layer to implement our business logic. HotChocolate supports dependency injection for resolvers. In this section, we will learn how to inject other services into the resolvers.

To demonstrate how to use dependency injection in HotChocolate, we will add an interface named ITeacherService and a class named TeacherService, as follows:

public interface ITeacherService{
    Task<Department> GetDepartmentAsync(Guid departmentId);
    Task<List<Teacher>> GetTeachersAsync();
    Task<Teacher> GetTeacherAsync(Guid teacherId);
    // Omitted for brevity
}
public class TeacherService(IDbContextFactory<AppDbContext> contextFactory) : ITeacherService
{
    ...

Interface and union types

HotChocolate supports the use of interfaces and union types in GraphQL. In this section, we will explore how to incorporate these features into your GraphQL schema. Interfaces provide a way to group types that share common fields, while union types allow for the creation of a single type that can return different object types. With HotChocolate, you can easily implement these features to enhance the functionality of your GraphQL schema.

Interfaces

To prepare the examples of GraphQL interfaces, we have an ISchoolRoom interface and two classes that implement the interface, as follows:

public interface ISchoolRoom{
    Guid Id { get; set; }
    string Name { get; set; }
    string? Description { get; set; }
    public int Capacity { get; set; }
}
public class LabRoom : ISchoolRoom
{
    public Guid Id { get; set; }
    public string...

Filtering, sorting, and pagination

In this section, we will learn how to implement filtering, sorting, and pagination in HotChocolate. These features are very important for a real-world application. We will use the Student object as an example to demonstrate how to implement these features. The Student class is defined as follows:

public class Student{
    public Guid Id { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string? Phone { get; set; }
    public string Grade { get; set; } = string.Empty;
    public DateOnly? DateOfBirth { get; set; }
    public Guid GroupId { get; set; }
    public Group Group { get; set; } = default!;
    public...

Visualizing the GraphQL schema

When the GraphQL API becomes more complex, it is difficult to understand the schema. We can use GraphQL Voyager to visualize the GraphQL schema. GraphQL Voyager is an open-source project that can visualize the GraphQL schema in an interactive graph. It is a frontend application that can be integrated with the GraphQL API. To use it in our ASP.NET Core application, we can use the GraphQL.Server.Ui.Voyager package. This package is part of the GraphQL.NET project.

Follow these steps to use GraphQL Voyager in our application:

  1. Install the GraphQL.Server.Ui.Voyager package using the following command:
    dotnet add package GraphQL.Server.Ui.Voyager
  2. Add the following code to the Program.cs file:
    app.MapGraphQLVoyager();

    The preceding code adds a middleware that maps the Voyager UI to the default URL ui/voyager. If you want to specify a different URL, you can pass the URL as a parameter, as in this example:

    app.MapGraphQLVoyager("/voyager");
  3. ...

Summary

In this chapter, we explored how to use HotChocolate and Entity Framework Core to create a GraphQL API. We discussed how to define object types, queries, and mutations, as well as how to use dependency injection to inject the DbContext instance and services into the resolver. We also introduced the data loader, which can reduce the number of queries to the database. Additionally, we discussed interface and union types, which are useful for defining polymorphic types. Finally, we explored how to use filtering, sorting, and pagination in HotChocolate.

In the next chapter, we will discuss SignalR, which is a real-time communication library in ASP.NET Core.

Further reading

It is important to note that GraphQL is a comprehensive query language and there are many features that we were unable to cover in this chapter. For example, GraphQL supports subscriptions, which enable real-time communication with the GraphQL API. To learn more about HotChocolate and GraphQL, please refer to the following resources:

In a microservice architecture, we can use Apollo Federation to create a GraphQL gateway. Apollo Federation can combine multiple GraphQL APIs into a single GraphQL API. We will not cover Apollo Federation here as it is out of the scope of this book. To learn more about Apollo Federation, please refer to the following resources:

lock icon The rest of the chapter is locked
You have been reading a chapter from
Web API Development with ASP.NET Core 8
Published in: Apr 2024 Publisher: Packt ISBN-13: 9781804610954
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}

Scalar type

Description

.NET type

Int

Signed 32-bit integer

int

Float

Signed double-precision floating-point value specified in IEEE 754

float or double

String

...