Hello Everyone
Today, we will delve into one of the modern API architectures.
GraphQL
GraphQL, developed by Facebook, is a modern API architecture that allows clients to request precisely the data they need. Unlike traditional REST APIs, GraphQL provides flexibility and efficiency in fetching data by enabling clients to query multiple resources in a single request.
GraphQL is a powerful query language for APIs, enabling clients to request exactly the data they need. With .NET 8 and the HotChocolate library, building a robust GraphQL API is straightforward. In this article, we'll create a GraphQL API to manage a collection of books using a book repository.
Prerequisites
Before diving in, ensure you have,
- .NET 8 SDK installed.
- Basic knowledge of C# and GraphQL.
Step 1. Setting Up the Project.
-
Create a new .NET 8 Web API project
dotnet new web -n GraphQLApi
cd GraphQLApi
- Add the HotChocolate NuGet packages
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Data
Step 2. Defining the Data Model.
Create a Book
class to represent the data.
namespace GraphQLApi
{
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
}
}
Step 3. Implementing the Repository.
The BookRepository handles CRUD operations. Here's the implementation.
namespace GraphQLApi
{
public class BookRepository
{
private readonly List<Book> _books = new()
{
new Book { Id = 1, Title = "C# in Depth", Author = "Jon Skeet" },
new Book { Id = 2, Title = "Clean Code", Author = "Robert C. Martin" }
};
public IQueryable<Book> GetBooks() => _books.AsQueryable();
public Book GetBook(int id) => _books.FirstOrDefault(x => x.Id == id);
public Book AddBook(Book book)
{
book.Id = _books.Max(b => b.Id) + 1;
_books.Add(book);
return book;
}
public Book UpdateBook(int id, Book book)
{
var bookDetail = GetBook(id);
if (bookDetail != null)
{
_books.Remove(bookDetail);
book.Id = bookDetail.Id;
_books.Add(book);
return book;
}
return null;
}
public bool DeleteBook(int id)
{
var bookDetail = GetBook(id);
if (bookDetail != null)
{
_books.Remove(bookDetail);
return true;
}
return false;
}
}
}
Step 4. Defining the GraphQL Schema.
Query Type
The Query
class defines methods to fetch data.
using GraphQLApi.Models;
using GraphQLApi.Repositories;
namespace GraphQLApi.GraphQL
{
public class Query
{
private readonly BookRepository _repository;
public Query(BookRepository repository)
{
_repository = repository;
}
public IQueryable<Book> GetBooks() => _repository.GetBooks();
public Book GetBook(int id) => _repository.GetBook(id);
}
}
Mutation Type
The Mutation class defines methods for modifying data.
namespace GraphQLApi
{
public class Mutation
{
private readonly BookRepository _repository;
public Mutation(BookRepository repository)
{
_repository = repository;
}
public Book AddBook(string title, string author)
{
var book = new Book { Title = title, Author = author };
return _repository.AddBook(book);
}
public Book UpdateBook(int id, string title, string author)
{
var book = new Book { Id = id, Title = title, Author = author };
return _repository.UpdateBook(id, book);
}
public bool DeleteBook(int id)
{
return _repository.DeleteBook(id);
}
}
}
Step 5. Configuring the GraphQL Server.
Update the Program.cs file to configure the GraphQL server.
using GraphQLApi;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Add services
builder.Services.AddSingleton<BookRepository>();
// Add GraphQL service support
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>()
.AddFiltering()
.AddSorting();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
// Configure the HTTP request pipeline
app.MapGraphQL();
app.Run();
Step 6. Running and Testing the API.
Run the application.
dotnet run
Open the GraphQL Playground in your browser at http://localhost:5000/graphql.
Example Queries and Mutations
Query All Books
query {
books {
id
title
author
}
}
Query a Single Book
query {
bookById(id:2) {
id
title
author
}
}
Add a New Book
mutation {
addBook( title: "New Book", author: "Author Name" ) {
id
title
author
}
}
Update an Existing Book
mutation {
updateBook(id: 2, title: "Updated Title", author: "Updated Author" ) {
id
title
author
}
}
Delete a Book
mutation {
deleteBook(id: 2)
}
Sample ScreenShot
GraphQL vs REST Comparision
Aspect |
GraphQL |
REST |
Endpoint |
Single endpoint for all operations. |
Multiple endpoints for different resources. |
Data Fetching |
Fetches only required fields in one query. |
Returns fixed data structures, often over-fetching or under-fetching. |
Flexibility |
Highly flexible; client defines the response. |
The server defines a response structure that is less flexible. |
Performance |
Combines multiple queries into one request. |
Requires multiple requests for related resources. |
Versioning |
No versioning is needed; it evolves with schema changes. |
Requires versioning for major updates (e.g., /v1, /v2). |
Real-Time |
Built-in support for subscriptions (real-time). |
Limited real-time capabilities; needs additional setup. |
Use Cases |
Best for complex, dynamic, or real-time needs. |
Ideal for simpler, well-defined APIs. |
Conclusion
With .NET 8 and HotChocolate, creating a GraphQL API is simple and efficient. This example demonstrates the core concepts of building and managing an API with queries and mutations. You can extend this implementation by adding advanced features like authorization and subscriptions or integrating with a database. For more details, check out this documentation link GraphQL
Happy coding!