M3: Web API — ASP.NET Core, OData, валидация, маппинг
На M3 проект защиты получает «лицо» — Web API поверх доменной модели и БД. Стажёр знакомится с большинством технологий слоя Application из боевого DeepGeo: валидация (FluentValidation), маппинг (Mapperly), спецификации (Ardalis.Specification), OData, NSwag. Также впервые упоминается MediatR — на уровне концепции.
⚠️ Уровень детализации. Постановка задачи и целевые навыки зафиксированы. Конкретные шаги реализации (состав эндпоинтов, форма спецификаций, структура DTO) — самостоятельное решение стажёра на основе материалов. Снять пометку и уточнить детали можно после сверки с
intern-development-strategy-design.md.
Срок
Месяц 4 Фазы 1 (~40–60 часов).
Цель
Построить REST/OData API над доменной моделью из M1–M2. API позволяет:
- читать
Project,Borehole,Sample,Sample_Lab,ParameterValue(с фильтрами и пагинацией через OData); - создавать новые записи;
- обновлять и удалять;
- запускать парсер из M1 по HTTP (загрузить файл → получить результат → сохранить в БД).
Целевые навыки
| Группа | Что осваивается |
|---|---|
| ASP.NET Core Web API | Контроллеры, маршрутизация, [HttpGet]/[HttpPost], статус-коды, async/await |
| OData | Гибкие запросы ($filter, $select, $expand, $top, $skip). Когда уместно, когда нет |
| FluentValidation | Валидация DTO отдельным классом-валидатором (а не data-annotations) |
| Riok.Mapperly | Маппинг домен ↔ DTO через source generator. Проекции на уровне EF Core |
| Ardalis.Specification | Паттерн «спецификация» для переиспользуемых запросов к данным |
| NSwag | Генерация Swagger/OpenAPI-описания API. Стажёр видел Swagger стенда — теперь строит свой |
| MediatR (концептуально) | Что такое CQRS, зачем разделение Command/Query. Без практики — только понимание |
| Serilog (концептуально) | Структурированное логирование. Базовая настройка |
Технологии на M3
Microsoft.AspNetCore.OData+Microsoft.OData.CoreFluentValidation+FluentValidation.DependencyInjectionExtensionsRiok.MapperlyArdalis.Specification+Ardalis.Specification.EntityFrameworkCoreNSwag.AspNetCoreSerilog.AspNetCore
Задание
Постановка
Построить Web API над моделью из M1–M2 так, чтобы все данные стали доступны по HTTP, а парсер можно было запускать загрузкой файла через эндпоинт.
Требования к результату
Контроллеры и эндпоинты
Спроектировать REST API для основных сущностей (Borehole, Sample — обязательно; Project, Sample_Lab, ParameterValue — на усмотрение). Для каждой сущности поддержать минимум:
- чтение списка;
- чтение одного по идентификатору;
- создание;
- обновление;
- удаление.
Как сгруппировать эндпоинты (по одному контроллеру на сущность / иерархически), какие URL использовать, что возвращать — самостоятельное решение. Руководствоваться принципами REST (в материалах ниже).
Какие HTTP-статусы возвращать в каком случае — самостоятельное решение, но должно быть согласовано: одно и то же условие (например, «не найдено») возвращает один и тот же статус во всех эндпоинтах.
Эндпоинт запуска парсера
Один из эндпоинтов принимает файл (CSV или JSON), прогоняет через парсер из M1 и сохраняет результат в БД через DbContext из M2. Возвращает итог: сколько объектов какого типа создано, какие warnings возникли.
OData
Минимум один эндпоинт (например, чтение списка Sample) должен поддерживать OData-запросы: фильтрацию ($filter), проекцию полей ($select), пагинацию ($top/$skip). Где именно подключать OData и к каким сущностям — самостоятельное решение. Подсказка для размышления: OData уместен там, где клиенту нужна гибкость запросов. Не везде его включать разумно.
DTO и валидация
Данные принимаются и возвращаются через DTO, а не через доменные классы напрямую. Маппинг домен ↔ DTO реализовать через Mapperly.
Валидация входных DTO — через FluentValidation. Минимум один валидатор с нетривиальным правилом (не просто [Required], а логика — например, «глубина отбора не может быть отрицательной» или DepthTo > DepthFrom).
Спецификация
Применить Ardalis.Specification минимум в одном месте, где это уместно. Например: «все образцы конкретной выработки с глубиной больше N» или «все ParameterValue данного Sample_Lab, отсортированные по коду параметра». Идея — encapsулировать условие выборки в переиспользуемый объект.
Swagger
API должен быть описан в Swagger UI (через NSwag или встроенный Swashbuckle — на выбор). Все эндпоинты видны, их можно дёрнуть из браузера. Описание и примеры в Swagger — большой плюс.
Логирование
Подключить Serilog для структурированного логирования. Минимум — логирование в консоль и файл. Что именно логировать (уровни, события) — самостоятельное решение.
MediatR (знакомство, без практики)
Изучить концептуально, без внедрения в код:
- что такое CQRS и зачем разделять чтение и запись;
- как MediatR реализует этот паттерк в .NET;
- почему в боевом DeepGeo выбран этот подход.
Это задел на Фазу 2 — при работе с основным репозиторием MediatR встретится везде.
Тесты
Покрыть API интеграционными тестами (WebApplicationFactory или аналогичный подход). Минимум — happy path по ключевым эндпоинтам (создание + чтение).
Инженерная культура
- DI-регистрация всех компонентов в
Program.cs. - Строка подключения и конфигурация — в
appsettings.json. - Коммиты осмысленные, ветки под задачи.
Контрольная точка
В конце месяца 4 — встреча с наставником:
- продемонстрировать API в Swagger UI;
- показать CRUD по основным сущностям;
- показать эндпоинт запуска парсера (загрузить файл, увидеть результат);
- показать, как работает OData на одном эндпоинте;
- показать FluentValidation-валидатор в действии (отправить невалидный DTO);
- объяснить, где применена спецификация и почему;
- показать логи Serilog.
Чек-лист завершения M3
- Контроллеры для основных сущностей реализованы
- CRUD покрыт интеграционными тестами
- FluentValidation-валидаторы работают (минимум один нетривиальный)
- Mapperly-мапперы генерируются
- Хотя бы один OData-эндпоинт работает
- Ardalis.Specification применена хотя бы один раз
- Swagger UI корректно описывает API
- Serilog пишет логи (минимум в консоль и файл)
- Эндпоинт запуска парсера по HTTP работает end-to-end
- Понимание CQRS/MediatR на концептуальном уровне (готовность объяснить)
Материалы по темам
ASP.NET Core Web API — основы
- metanit.com — ASP.NET Core — основная глава.
- metanit.com — Web API
- metanit.com — Контроллеры
- Microsoft Learn — Создание Web API (RU)
HTTP и REST (если нужно освежить)
OData
- Microsoft Learn — OData (EN) — концептуально.
FluentValidation
Mapperly
- Mapperly — GitHub — документация и примеры.
Ardalis.Specification
- Ardalis.Specification — GitHub — README с примерами.
NSwag и Swagger
Serilog
- Serilog — GitHub — README с quick start.
MediatR (только чтение, без практики)
- MediatR — GitHub — README + wiki.
- CQRS простыми словами (RU, Хабр)
Прогресс
[■■■■□] M3 из 5 вех — API готов, данные доступны по HTTP.
- ⬅️ M2 — персистентность
- ➡️ M4 — UI и подготовка к защите — финальная веха
- 🐛 QA-трек — параллельный поток работы с багами
- ✅ Чек-листы — критерии прохождения вех
📚 Полный список ресурсов — в разделе Ресурсы.