Введение в GraphQL на платформе .NET
GraphQL — это язык запросов для API, который предоставляет клиентам возможность получать только те данные, которые им действительно нужны. В отличие от REST, где структура ответа жестко определена сервером, GraphQL позволяет гибко формировать запросы. В этом туториале мы создадим полноценный GraphQL API на C# с использованием фреймворка Hot Chocolate — самого популярного решения для .NET.
Мы пройдем путь от установки до создания сложных запросов с мутациями и подписками. Статья рассчитана на разработчиков, знакомых с основами C# и ASP.NET Core.
1. Настройка проекта и установка зависимостей
Для начала создадим новый проект ASP.NET Core. Вы можете использовать Visual Studio, Rider или командную строку.
dotnet new web -n GraphQLDemo
cd GraphQLDemo
Теперь установим пакет Hot Chocolate — основной инструмент для работы с GraphQL в .NET:
dotnet add package HotChocolate.AspNetCore
Дополнительно для работы с запросами через GraphQL IDE (Banana Cake Pop) установим:
dotnet add package HotChocolate.AspNetCore.Playground
1.1 Базовая конфигурация Program.cs
Откройте файл Program.cs и настройте сервисы:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>();
var app = builder.Build();
app.MapGraphQL();
app.Run();
Обратите внимание: мы регистрируем Query — это наш корневой тип для чтения данных. Пока он пуст, но мы его наполним.
2. Создание модели данных и первого запроса
GraphQL работает с типами. Создадим простую модель Book:
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int Year { get; set; }
}
Теперь определим класс Query, который будет возвращать данные:
public class Query
{
private static List<Book> _books = new()
{
new Book { Id = 1, Title = "1984", Author = "George Orwell", Year = 1949 },
new Book { Id = 2, Title = "Clean Code", Author = "Robert C. Martin", Year = 2008 }
};
public IQueryable<Book> GetBooks() => _books.AsQueryable();
public Book? GetBookById(int id) => _books.FirstOrDefault(b => b.Id == id);
}
Запустите приложение и откройте http://localhost:5000/graphql. Вы увидите Banana Cake Pop — встроенную IDE для тестирования запросов. Попробуйте выполнить:
{
books {
title
author
}
}
Вы получите только те поля, которые запросили — в этом сила GraphQL.
3. Мутации для изменения данных
Мутации — это аналог POST/PUT/DELETE в REST. Они позволяют изменять данные на сервере. Добавим возможность добавлять новые книги.
3.1 Определение входного типа
Создадим класс для входных данных мутации:
public class AddBookInput
{
public string Title { get; set; }
public string Author { get; set; }
public int Year { get; set; }
}
3.2 Реализация мутации
Добавим класс Mutation:
public class Mutation
{
private static List<Book> _books = new()
{
new Book { Id = 1, Title = "1984", Author = "George Orwell", Year = 1949 },
new Book { Id = 2, Title = "Clean Code", Author = "Robert C. Martin", Year = 2008 }
};
public Book AddBook(AddBookInput input)
{
var newBook = new Book
{
Id = _books.Max(b => b.Id) + 1,
Title = input.Title,
Author = input.Author,
Year = input.Year
};
_books.Add(newBook);
return newBook;
}
}
Не забудьте зарегистрировать мутацию в Program.cs:
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>();
Теперь можно выполнить мутацию через Banana Cake Pop:
mutation {
addBook(input: { title: "Dune", author: "Frank Herbert", year: 1965 }) {
id
title
}
}
4. Подписки (Subscriptions) для real-time уведомлений
Подписки позволяют клиентам получать уведомления в реальном времени при изменениях данных. Это полезно для чатов, уведомлений или ленты новостей.
4.1 Настройка WebSocket
Установите дополнительный пакет:
dotnet add package HotChocolate.AspNetCore.Subscriptions
Добавьте поддержку WebSocket в Program.cs:
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>()
.AddSubscriptionType<Subscription>();
app.UseWebSockets();
4.2 Реализация подписки
Создадим класс Subscription:
public class Subscription
{
[Subscribe]
public Book OnBookAdded([EventMessage] Book book) => book;
}
Теперь нужно изменить мутацию, чтобы она публиковала событие при добавлении книги. Используем интерфейс ITopicEventSender:
public class Mutation
{
public async Task<Book> AddBookAsync(AddBookInput input, [Service] ITopicEventSender eventSender)
{
var newBook = new Book { ... };
await eventSender.SendAsync(nameof(Subscription.OnBookAdded), newBook);
return newBook;
}
}
Теперь клиенты могут подписаться на добавление книг:
subscription {
onBookAdded {
id
title
author
}
}
5. Фильтрация, сортировка и пагинация
Hot Chocolate поддерживает встроенные возможности для фильтрации и сортировки. Установите пакет:
dotnet add package HotChocolate.Data
Обновите метод получения книг в Query:
public class Query
{
[UseFiltering]
[UseSorting]
public IQueryable