GraphQL API с C#: Пошаговое руководство для .NET разработчиков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в GraphQL и C#

GraphQL — это язык запросов для API, который предоставляет клиентам возможность запрашивать только те данные, которые им действительно нужны. В отличие от REST, где структура ответа фиксирована, GraphQL позволяет гибко формировать запросы и получать ровно то, что требуется. В этом туториале мы разберём, как создать полноценный GraphQL API на платформе C# (.NET) с использованием библиотеки Hot Chocolate.

Этот материал будет полезен как новичкам, так и опытным разработчикам, которые хотят освоить современный подход к построению API. Мы пройдём все этапы: от настройки проекта до реализации запросов и мутаций. К концу статьи у вас будет работающий GraphQL-сервер, готовый к интеграции с любым клиентом.

Установка и настройка проекта

Первым делом нам нужно создать новый проект ASP.NET Core. Откройте терминал или командную строку и выполните команду:

dotnet new web -n GraphQLDemo
cd GraphQLDemo

Теперь добавим пакет Hot Chocolate — это основная библиотека для работы с GraphQL в .NET:

dotnet add package HotChocolate.AspNetCore

После установки откройте файл Program.cs и настройте сервисы. Вот минимальная конфигурация для запуска GraphQL:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Добавляем GraphQL сервисы
builder.Services
    .AddGraphQLServer()
    .AddQueryType<Query>();

var app = builder.Build();

// Подключаем middleware для GraphQL
app.MapGraphQL();

app.Run();

Обратите внимание: мы ещё не создали класс Query. Это наш корневой тип, который определяет доступные запросы. Создадим его в следующем разделе.

Определение схемы: типы и резолверы

Создание модели данных

Для начала определим простую модель данных. Пусть это будет книга:

public class Book
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public int Year { get; set; }
}

Создание Query-класса

Теперь создадим класс Query, который будет возвращать данные. В Hot Chocolate резолверы — это обычные методы, которые могут быть синхронными или асинхронными:

public class Query
{
    private static readonly List<Book> Books = new()
    {
        new Book { Id = "1", Title = "Война и мир", Author = "Лев Толстой", Year = 1869 },
        new Book { Id = "2", Title = "Преступление и наказание", Author = "Фёдор Достоевский", Year = 1866 }
    };

    public IQueryable<Book> GetBooks() => Books.AsQueryable();

    public Book? GetBook(string id) => Books.FirstOrDefault(b => b.Id == id);
}

Метод GetBooks возвращает список всех книг, а GetBook — одну книгу по идентификатору. Hot Chocolate автоматически преобразует эти методы в поля GraphQL-схемы.

Настройка типов (опционально)

Иногда нужно явно указать, какие поля должны быть доступны. Для этого можно использовать атрибуты или Fluent API. Пример с атрибутами:

public class Book
{
    [GraphQLName("id")]
    public string Id { get; set; }

    [GraphQLNonNullType]
    public string Title { get; set; }

    public string Author { get; set; }
    public int Year { get; set; }
}

Теперь запустите проект командой dotnet run и перейдите в браузере по адресу http://localhost:5000/graphql. Вы увидите встроенную Banana Cake Pop — среду для тестирования запросов.

Реализация мутаций (создание, обновление, удаление)

Мутации в GraphQL используются для изменения данных. Создадим класс Mutation и добавим методы для работы с книгами.

public class Mutation
{
    private static readonly List<Book> Books = new()
    {
        new Book { Id = "1", Title = "Война и мир", Author = "Лев Толстой", Year = 1869 }
    };

    public Book AddBook(string title, string author, int year)
    {
        var book = new Book
        {
            Id = Guid.NewGuid().ToString(),
            Title = title,
            Author = author,
            Year = year
        };
        Books.Add(book);
        return book;
    }

    public bool DeleteBook(string id)
    {
        var book = Books.FirstOrDefault(b => b.Id == id);
        if (book != null)
        {
            Books.Remove(book);
            return true;
        }
        return false;
    }
}

Не забудьте зарегистрировать Mutation в Program.cs:

builder.Services
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddMutationType<Mutation>();

Теперь в Banana Cake Pop вы можете выполнить мутацию:

mutation {
  addBook(title: "Мастер и Маргарита", author: "Михаил Булгаков", year: 1967) {
    id
    title
    author
  }
}

Ответ вернёт созданный объект с указанными полями. Обратите внимание: мы сами решаем, какие поля возвращать — это и есть сила GraphQL.

Фильтрация, пагинация и лучшие практики

Фильтрация данных

Hot Chocolate поддерживает фильтрацию «из коробки». Установите пакет:

dotnet add package HotChocolate.Data

Затем добавьте атрибут [UseFiltering] к вашему резолверу:

public class Query
{
    [UseFiltering]
    public IQueryable<Book> GetBooks() => Books.AsQueryable();
}

Теперь клиент может фильтровать книги:

{
  books(where: { author: { eq: "Лев Толстой" } }) {
    title
    year
  }
}

Пагинация

Для пагинации используйте атрибут [UsePaging]:

[UsePaging]
public IQueryable<Book> GetBooks() => Books.AsQueryable();

Запрос с пагинацией будет выглядеть так:

{
  books(first: 2) {
    nodes {
      title
    }
    pageInfo {                

Блоги

Рекомендаций по книгам