Minimal API в ASP.NET Core позволяет написать первый HTTP endpoint без контроллеров и лишней структуры проекта. Это хороший следующий шаг после консольных уроков: вы уже знаете C#-код, dotnet run, классы и JSON, а теперь увидите, как из этого получается локальный web API
В этом уроке сделаем /health, /tasks и /tasks/{id}, проверим ответы через браузер или curl
Что получится в конце
Команда:
dotnet run
запустит локальный сервер. Запрос:
curl http://localhost:5000/health
вернет:
{"status":"ok"}
А запрос:
curl http://localhost:5000/tasks/1
вернет задачу по ID
Создаем проект
dotnet new web -n CSharpMinimalApi
cd CSharpMinimalApi
Откройте Program.cs. Замените содержимое:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var tasks = new List<TaskItem>
{
new(1, "Разобрать Minimal API", true),
new(2, "Добавить endpoint /tasks", false)
};
app.MapGet("/health", () => new { status = "ok" });
app.MapGet("/tasks", () => tasks);
app.MapGet("/tasks/{id:int}", (int id) =>
{
var task = tasks.FirstOrDefault(task => task.Id == id);
return task is null
? Results.NotFound(new { error = "task not found" })
: Results.Ok(task);
});
app.Run("http://localhost:5000");
public record TaskItem(int Id, string Title, bool Done);
Запустите:
dotnet run
Что делает WebApplication
Строки:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
создают и настраивают приложение ASP.NET Core. В большом проекте через builder добавляют сервисы, настройки, логирование, базу данных, Swagger. В первом уроке оставляем минимум
app.Run("http://localhost:5000") запускает сервер на понятном локальном адресе. Можно не задавать адрес руками, но для урока так проще проверять запросы
Первый endpoint
Endpoint:
app.MapGet("/health", () => new { status = "ok" });
говорит: на GET-запрос /health вернуть объект со статусом. ASP.NET Core сам сериализует объект в JSON
Проверка:
curl http://localhost:5000/health
Если в браузере открыть тот же адрес, вы тоже увидите JSON
Endpoint со списком
app.MapGet("/tasks", () => tasks);
возвращает список задач. TaskItem объявлен как record, потому что это компактная модель данных:
public record TaskItem(int Id, string Title, bool Done);
Для первого API это удобно. В реальном проекте модели часто выносят в отдельные файлы
Route parameter
Маршрут:
"/tasks/{id:int}"
содержит параметр id. Ограничение :int означает, что endpoint подходит для числового ID
Handler принимает этот ID:
(int id) =>
и ищет задачу:
var task = tasks.FirstOrDefault(task => task.Id == id);
Если задача не найдена, возвращаем 404:
Results.NotFound(new { error = "task not found" })
Если найдена, возвращаем 200 OK:
Results.Ok(task)
Проверяем ответы
curl http://localhost:5000/tasks
curl http://localhost:5000/tasks/1
curl http://localhost:5000/tasks/999
Для последнего запроса должен прийти ответ с ошибкой task not found
Если хотите увидеть заголовки и статус:
curl -i http://localhost:5000/tasks/999
Что не делаем в первом уроке
Не подключаем базу данных, авторизацию, Swagger, Docker и слои архитектуры. Это все полезно, но если добавить сразу, новичок перестанет видеть базовую механику endpoint
Сначала нужно понять цепочку: маршрут -> handler -> данные -> JSON response -> status code
Частые ошибки
Порт занят. Если localhost:5000 уже используется, поменяйте порт в app.Run
curl не видит сервер. Проверьте, что dotnet run продолжает работать в отдельном окне терминала
FirstOrDefault не найден. Проверьте, что подключены стандартные using или включены implicit usings в проекте
Возвращается не тот статус. Для ошибок используйте Results.NotFound, Results.BadRequest, Results.Problem, а не просто строку с текстом ошибки
Что может быть еще интересно по этой теме
Minimal API заменяет контроллеры? Не полностью. Для небольших API и микросервисов Minimal API удобен. В крупных проектах контроллеры и слои все еще могут быть уместны
Можно ли сразу подключить базу? Можно, но лучше после понимания endpoint и JSON. Иначе база смешается с маршрутизацией
Почему JSON создается автоматически? ASP.NET Core умеет сериализовать возвращаемые объекты в HTTP-ответ
Что учить после первого endpoint? POST-запросы, валидацию, dependency injection, configuration, логирование и работу с базой данных
Что открыть дальше
- JSON и файлы в C#: читаем настройки проекта — чтобы понимать сериализацию объектов.
- async await в C#: первый пример без магии — endpoints часто делают асинхронными.
- List, Dictionary и LINQ в C# на живом примере — список задач здесь фильтруется через LINQ.
- C# и .NET Framework: что выбрать новичку — чтобы отделить современный ASP.NET Core от старого .NET Framework.



