Перейти к основному содержимому

Первая программа на ASP.NET Core

Разработчику Архитектору

Play ITЗагрузка интерактивного демо…


Первая программа на ASP.NET Core

Модель HTTP для первого проекта

При переходе из консольного C# в веб достаточно цепочки: приложение слушает порт → клиент шлёт HTTP-запрос → обработчик возвращает статус и тело → результат виден в браузере или curl.

ЧтоГдеЗачем
Маршруты и пайплайнProgram.csКакие URL существуют
Контрактыrecord/DTOФормат JSON
Проверка живости/healthСервер отвечает

Что такое ASP.NET Core

Консольная программа общается с пользователем через терминал. Веб-приложение общается по сети по протоколу HTTP — клиент (браузер, мобильное приложение, другой сервер) отправляет запрос (URL, метод, заголовки, иногда тело), сервер возвращает ответ (код статуса, заголовки, тело — часто JSON или HTML).

ASP.NET Core — фреймворк Microsoft для таких серверов на C#:

  • принимает HTTP (встроенный сервер Kestrel);
  • направляет запрос по маршруту к нужному коду;
  • собирает ответ (JSON, файл, редирект);
  • подключает DI (внедрение зависимостей) — общие сервисы в одном месте.

Мы соберём минимальный REST API "Заметки" без базы данных: список хранится в памяти, зато проходим полный цикл запрос → маршрут → обработчик → ответ. Углубление без контроллеров: Minimal API и OpenAPI. Пример с PostgreSQL: Приложение с S3, PostgreSQL и ASP.NET Core Web API. Теория: ASP.NET. HTML: Razor Pages. Auth: Identity — JWT и cookie. Тесты: Тесты ASP.NET Core — юнит и интеграция. UI: Blazor · MAUI.


Словарь HTTP и API

ТерминПростыми словами
HTTP-методДействие: GET — прочитать, POST — создать, PUT/PATCH — изменить, DELETE — удалить.
URL / маршрутАдрес ресурса, например /api/notes или /hello/World.
REST APIСтиль API: ресурсы — существительные в URL, операции — HTTP-методы; ответ часто JSON.
JSONТекстовый формат { "text": "заметка" } — удобен для программ.
КонтроллерКласс с методами, привязанными к маршрутам ([HttpGet], [HttpPost]).
Minimal APIТе же маршруты, но объявлены в Program.cs через MapGet / MapPost.
Swagger / OpenAPIСтраница в браузере со списком эндпоинтов и кнопкой "Try it out".
DIКонтейнер создаёт сервисы (IGreetingService) и подставляет их в обработчики.

Что получится

МетодURLДействие
GET/healthПроверка "сервер жив"
GET/hello/{name}JSON-приветствие
GET/POST/api/notesСписок и создание заметок (вариант с контроллером)

После dotnet run откройте Swagger UI — интерактивную документацию API в браузере.

Разбор:

  • Диаграмма показывает полный путь запроса от клиента к серверу и обратно.
  • Kestrel принимает HTTP-соединение и создаёт контекст запроса.
  • Middleware — инфраструктура для всех запросов — HTTPS, auth, логи, глобальные ошибки.
  • Routing выбирает endpoint; только после этого имеет смысл логика, завязанная на конкретный маршрут.
  • Endpoint filter и policy pipeline на первом проекте могут отсутствовать — их добавляют, когда проверок становится много (см. ASP.NET - фреймворк для веб-приложений — где жить логике).
  • Handler — сценарий: MapGet, Minimal API delegate или метод контроллера.
  • JSON 200 — успешный ответ с телом.
Куда класть проверки

Не смешивайте инфраструктуру (middleware), привязку к маршруту (endpoint filter) и бизнес-регуляции (policy pipeline) в одном handler. Критерии выбора и примеры — в обзоре ASP.NET (451).


Требования

  • .NET SDK 8 или 9 (dotnet --version)
dotnet --version

Разбор:

  • dotnet --version выводит текущую версию установленного .NET SDK.

  • Команда подтверждает, что окружение готово к созданию и запуску проекта.

  • Проверка версии особенно важна, когда вы повторяете материал на другой машине или в CI.

  • Редактор: Visual Studio, Rider или VS Code + C# Dev Kit


Создание проекта

dotnet new webapi -n HelloApi -o HelloApi --use-controllers
cd HelloApi
dotnet run

Разбор:

  • dotnet new webapi создаёт проект из шаблона ASP.NET Core Web API.
  • -n HelloApi задаёт имя проекта, -o HelloApi — папку вывода.
  • --use-controllers включает контроллерный стиль и готовую MVC-инфраструктуру.
  • cd HelloApi переводит терминал в каталог созданного проекта.
  • dotnet run собирает приложение и запускает Kestrel с локальными URL.
Часть командыСмысл
webapiШаблон веб-API с контроллерами и Swagger.
--use-controllersЯвно включить классические контроллеры.

В консоли появятся адреса вроде https://localhost:7xxx и http://localhost:5xxx. Откройте https://localhost:7xxx/swagger — шаблон уже содержит sample controller.

HTTPS — шифрованное соединение; в разработке браузер может предупредить о самоподписанном сертификате. curl с флагом -k игнорирует проверку сертификата.


Минимальный API (без контроллеров)

Удалите папку Controllers (или sample-контроллер) и замените Program.cs:

Код ITЗагрузка примера кода…

Разбор:

  • WebApplication.CreateBuilder(args) формирует основу приложения: конфигурацию, логирование и DI-контейнер.
  • AddEndpointsApiExplorer() добавляет метаданные endpoint-ов для генерации OpenAPI.
  • AddSwaggerGen() подключает генератор Swagger-документации.
  • builder.Build() собирает pipeline обработки запросов.
  • Проверка app.Environment.IsDevelopment() ограничивает Swagger режимом разработки.
  • MapGet("/health", ...) регистрирует endpoint для health-check.
  • MapGet("/hello/{name}", ...) демонстрирует параметр маршрута и его биндинг в string name.
  • Results.Ok(...) отправляет 200 OK и JSON-тело.
  • app.Run() запускает веб-сервер и начинает приём HTTP-запросов.

Разбор Program.cs

СтрокаСмысл
WebApplication.CreateBuilder(args)Создать "строитель" приложения: конфиг, логи, DI.
AddEndpointsApiExplorer()Собрать метаданные маршрутов для OpenAPI.
AddSwaggerGen()Подключить генерацию документации Swagger.
var app = builder.Build()Собрать pipeline и хост.
IsDevelopment()В режиме разработки включаем Swagger.
MapGet("/health", ...)На GET /health вернуть JSON { "status": "ok" }.
MapGet("/hello/{name}", ...)Сегмент {name} из URL попадает в параметр string name.
Results.Ok(...)Ответ с кодом 200 и телом (сериализуется в JSON).

Проверка из терминала (порт замените на свой):

dotnet run
curl https://localhost:5001/health -k
curl https://localhost:5001/hello/World -k

Разбор:

  • dotnet run стартует приложение и открывает локальные HTTP/HTTPS-адреса.
  • curl .../health проверяет, что endpoint жив и отвечает корректно.
  • curl .../hello/World тестирует маршрут с сегментом {name}.
  • Ключ -k отключает строгую проверку локального self-signed HTTPS-сертификата.

Вариант с контроллером

Controllers/NotesController.cs:

Код ITЗагрузка примера кода…

Разбор:

  • [ApiController] включает API-соглашения: автопривязку входных данных и автопроверку модели.
  • [Route("api/[controller]")] задаёт базовый путь контроллера по его имени.
  • ControllerBase подходит для API без HTML-представлений.
  • static List<Note> хранит данные в памяти процесса и подходит для учебного примера.
  • [HttpGet] помечает метод чтения коллекции, [HttpPost] — метод создания.
  • CreatedAtAction(...) возвращает 201 Created и сообщает клиенту адрес созданного ресурса.
  • record-типы описывают DTO компактно и удобно сериализуются в JSON.
Атрибут / элементСмысл
[ApiController]Соглашения Web API: привязка JSON из тела, валидация.
[Route("api/[controller]")]Базовый путь api/Notes.
: ControllerBaseAPI без HTML-представлений.
static List<Note>Учебное хранилище в памяти.
CreatedAtActionОтвет 201 Created + заголовок Location.
recordКомпактный DTO для JSON.

Program.cs для контроллеров:

builder.Services.AddControllers();
// ...
app.MapControllers();

Разбор:

  • AddControllers() регистрирует MVC-компоненты: роутинг контроллеров, model binding и JSON-форматтеры.
  • MapControllers() подключает к pipeline все маршруты, описанные атрибутами в контроллерах.
  • Вместе эти строки включают контроллерный стиль поверх базового хоста ASP.NET Core.

Внедрение зависимостей

Services/IGreetingService.cs:

public interface IGreetingService
{
string Greet(string name);
}

public class GreetingService : IGreetingService
{
public string Greet(string name) => $"Hello, {name}!";
}

Разбор:

  • interface IGreetingService задаёт контракт сервиса, который можно подменять в тестах или в других реализациях.
  • GreetingService реализует этот контракт и изолирует логику приветствия.
  • Метод Greet принимает имя и возвращает готовую строку для API-ответа.
  • Такой сервис статичен по поведению и подходит для регистрации как singleton.

Program.cs:

builder.Services.AddSingleton<IGreetingService, GreetingService>();

app.MapGet("/greet/{name}", (string name, IGreetingService svc) =>
Results.Ok(new { message = svc.Greet(name) }));

Разбор:

  • AddSingleton<IGreetingService, GreetingService>() создаёт единственный экземпляр сервиса на всё время работы приложения.
  • В MapGet зависимость IGreetingService svc подставляется контейнером DI автоматически.
  • Вызов svc.Greet(name) отделяет бизнес-логику от инфраструктурного кода endpoint-а.
  • Results.Ok(...) формирует стандартный JSON-ответ с кодом 200.
РегистрацияКогда использовать
AddSingletonОдин экземпляр на всё приложение.
AddScopedОдин экземпляр на HTTP-запрос (DbContext).
AddTransientНовый экземпляр при каждом разрешении.

Тестирование

В конце Program.cs добавьте public partial class Program { } — для WebApplicationFactory<Program>.

Полный разбор: интеграционные тесты ASP.NET Core.

dotnet test

Разбор:

  • dotnet test запускает автоматические тесты проекта и выводит результат по каждому тест-кейсу.
  • Это быстрая проверка, что изменения не сломали маршруты, сервисы и контракты.
  • Команду обычно запускают перед коммитом и перед публикацией.

Публикация

dotnet publish -c Release -o ./publish

Разбор:

  • dotnet publish готовит артефакт для развёртывания на сервере или в контейнере.
  • -c Release включает оптимизированную сборку для production-сценариев.
  • -o ./publish складывает все выходные файлы в отдельный каталог, удобный для деплоя.

Запуск на сервере: dotnet HelloApi.dll или Docker-образ на базе mcr.microsoft.com/dotnet/aspnet.

dotnet HelloApi.dll

Разбор:

  • Команда запускает уже опубликованное приложение из DLL.
  • Этот способ типичен для framework-dependent развёртывания, где runtime установлен на сервере.
  • Перед запуском обычно задают окружение и конфигурацию через переменные среды.

Частые ошибки

СимптомПричина
Swagger не открываетсяОкружение не Development или не подключён UseSwagger
404 на маршрутеОпечатка в URL; для контроллера — нет MapControllers()
DI не резолвит сервисНет AddSingleton / AddScoped в Program.cs
Пустое тело POSTНет Content-Type: application/json

Что попробовать

  1. MapPost с телом { "text": "..." } и record.
  2. Minimal API и OpenAPI.
  3. Клиент из MAUI: HttpClient.GetFromJsonAsync.

Мини-практикум — довести API до "полезного минимума"

После первой версии обычно делают четыре коротких шага:

  1. Добавляют CreatedAtAction на POST для корректного 201.
  2. Проверяют входные данные (string.IsNullOrWhiteSpace, StringLength).
  3. Выносят логику в сервис и подключают DI.
  4. Добавляют интеграционный тест на ключевой маршрут (Тесты ASP.NET Core — юнит и интеграция).

Так вы быстро переходите от "демо работает" к "минимальный production-подход".


Дальше


Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Первые шаги (маршрут подборки) — ADO.NET / Dapper — первая программа, Blazor — первая программа, EF Core — первая программа, .NET MAUI — первая программа, Первая программа на JavaFX, Razor Pages — первая программа.