Введение: API — это не страшно, а очень удобно
Представьте, что вы заказываете пиццу. Вы звоните в ресторан, диктуете адрес и состав — и через 30 минут курьер у двери. API в программировании работает точно так же: это тот самый «телефонный звонок», с помощью которого одна программа общается с другой. Только вместо голоса — HTTP-запросы, а вместо пиццы — данные.
В мире C# разработки API — это база. Любой современный проект, будь то веб-приложение, мобильный бэкенд или корпоративный сервис, так или иначе «дёргает» внешние сервисы. И тут встаёт главный вопрос: какой протокол выбрать? REST, GraphQL или gRPC? Каждый из них хорош по-своему, но каждый — для своей задачи.
В этой статье мы разберём работу с API на C# на реальных примерах. Вы узнаете, как отправлять HTTP-запросы, как подружить C# с GraphQL и gRPC, и, главное — поймёте, когда что использовать. Поехали!
1. REST API на C#: классика, которая не стареет
REST (Representational State Transfer) — это архитектурный стиль, который уже много лет остаётся стандартом де-факто. Простой, понятный, работает поверх HTTP. Если вы когда-либо писали код, который отправляет GET или POST запросы — вы уже работали с REST.
Как отправлять REST-запросы в C#
В C# для работы с REST чаще всего используют класс HttpClient. Он встроен в .NET и умеет всё: от простых GET-запросов до сложных POST с JSON-телом.
Вот как выглядит типичный запрос к REST API на C#:
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api.example.com/");
HttpResponseMessage response = await client.GetAsync("users/1");
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
}
}
}
Коротко и ясно. HttpClient живёт долго, поэтому его обычно создают один раз и переиспользуют (в реальных проектах — через DI-контейнер).
Когда REST — ваш выбор
- Вы пишете публичное API для веба или мобильных приложений.
- Клиенты — браузеры, мобильные устройства, IoT.
- Вам нужна простота и кэширование на уровне HTTP.
Минусы REST: избыточность данных (часто приходит больше, чем нужно) и проблема N+1 запросов, когда для получения связанных данных приходится делать несколько вызовов.
2. GraphQL на C#: запрашивай только то, что нужно
GraphQL — это язык запросов, созданный Facebook. Его главная фишка: клиент сам решает, какие поля ему нужны. Никакой лишней информации, никаких десятков эндпоинтов — один запрос, один ответ.
Отправляем GraphQL-запрос из C#
Для работы с GraphQL на C# можно использовать HttpClient напрямую, но удобнее взять библиотеку GraphQL.Client (NuGet-пакет GraphQL.Client).
Пример запроса к GraphQL API:
using System;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Client.Http;
using GraphQL.Client.Serializer.Newtonsoft;
class Program
{
static async Task Main(string[] args)
{
using var client = new GraphQLHttpClient("https://api.example.com/graphql", new NewtonsoftJsonSerializer());
var request = new GraphQLRequest
{
Query = @"
{
user(id: 1) {
name
email
posts {
title
}
}
}"
};
var response = await client.SendQueryAsync<dynamic>(request);
Console.WriteLine(response.Data);
}
}
Обратите внимание: в одном запросе мы получили и пользователя, и его посты. В REST для этого пришлось бы делать два запроса или использовать сложные вложенные эндпоинты.
Когда GraphQL выигрывает
- Сложные, глубоко вложенные данные (соцсети, каталоги).
- Мобильные приложения, где каждый килобайт на счету.
- Микросервисная архитектура: один GraphQL-шлюз объединяет данные из нескольких сервисов.
Минусы GraphQL: сложность кэширования, более высокая нагрузка на сервер (парсинг запросов), крутая кривая обучения для бэкенд-разработчиков.
3. gRPC на C#: скорость и строгость
gRPC — это протокол от Google, основанный на HTTP/2 и Protocol Buffers. Он не шутит: бинарный формат, строгие контракты, стриминг в обе стороны. Если REST — это велосипед, а GraphQL — гоночный автомобиль, то gRPC — это реактивный истребитель.
Как работать с gRPC в C#
Сначала нужно определить контракт в файле .proto:
syntax = "proto3";
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
message UserRequest {
int32 id = 1;
}
message UserResponse {
string name = 1;
string email = 2;
}
Затем сгенерировать код (это делает Visual Studio или dotnet build с пакетом Grpc.Tools). А дальше — вызывать сервис как обычный метод:
using Grpc.Net.Client;
using GrpcGreeterClient;
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new UserService.UserServiceClient(channel);
var reply = await client.GetUserAsync(new UserRequest { Id = 1 });
Console.WriteLine($"Name: {reply.Name}, Email: {reply.Email}");
Всё строго, типизированно, без JSON-сериализации. Работает молниеносно.
Где gRPC незаменим
- Внутренние микросервисы (высокая производительность).
- Системы реального времени (стриминг, чаты, лайв-данные).
- IoT и мобильные устройства (экономия трафика).
Минусы gRPC: не поддерживается браузерами напрямую (требуется gRPC-Web), сложнее в отладке (бинарный трафик), жёсткие контракты — любое изменение требует перегенерации кода.