Разработка API
API — это граница HTTP службы Lino. Они раскрывают варианты использования уровня приложения, не смешивая проблемы транспорта с правилами домена. В этой главе объясняется, как Lino генерирует Minimal APIs, контракты запросов/ответов, typed clients, метаданные OpenAPI и автоматическую регистрацию endpoints генераторами источников.
Сгенерированный endpoint должен оставаться тонким: получает данные HTTP, собирает команду или запрос, отправляет ее на уровень приложения через ISender и преобразует результат в typed response. Проверка, бизнес-правила, сохранение, транзакции и авторизация домена продолжаются в командах, запросах, обработчиках, валидаторах, репозиториях и Unit of Work.
Minimal APIs на Lino
Lino использует ядро ASP.NET Minimal APIs в качестве стандарта для создания endpoints, поскольку они сохраняют код прямым, явным и производительным, не нарушая границ Clean Architecture.
В текущих проектах Lino сгенерированные endpoints представляют собой минимальные классы API, реализующие IEndpoint. Каждая endpoint предоставляет статический метод MapEndpoint(IEndpointRouteBuilder app) и метод обработчика, который использует ISender для отправки сгенерированной команды или запроса на уровень приложения.
Сгенерированные основные части
*Endpoint.cs: метод карт HTTP, маршрут, метаданные, авторизация, требования клиента, ограничение скорости и версия.*Request.cs: представляет входные данные, поступающие из тела, строки запроса, параметров маршрута или данных формы.*Extensions.cs: преобразует запрос в команду/запрос и преобразует результат приложения в ответ HTTP.*Response.cs: определяет строго типизированный контракт, возвращаемый endpoint и typed clients.
Встроенные функции
Lino использует TypedResults и Results<...> чтобы ответы об успехе и ошибках были явными в коде и правильно отображались в OpenAPI. Ошибки, поступающие с прикладного уровня, преобразуются в ProblemDetails помещать result.MapToProblemDetails().
WithTags: группирует endpoints по модулю, объекту или функции в OpenAPI и Scalar.WithName: устанавливает согласованный идентификатор операции, если это применимо.WithSummary: четко описывает назначение endpoint.Produces(statusCode, schema): указывает коды состояния и контракты ответа.MapToApiVersion(1, 0): связывает endpoint с версией API.RequirePermission,RequireAuthorization,AllowAnonymousиRequireTenant: применить безопасность в соответствии с параметрами проекта.- Ограничение скорости на уровне группы или endpoint с использованием политик аутентификации или анонимности в зависимости от конфигурации.
Запросы и ответы
По умолчанию Lino использует records для запросов и ответов. Они краткие, неизменяемые по умолчанию и хорошо работают как явные контракты между API, typed clients и внешними потребителями.
- Запросы, полученные через endpoint, преобразуются в команды или запросы.
- Результаты команд или запросов преобразуются в ответы.
- Объекты домена не должны быть напрямую представлены как контракт HTTP.
public record CreatePersonRequest(string Name, int Age); public record CreatePersonResponse(Guid Id, string Name, int Age);
Создание новых API
Создайте API с помощью CLI, когда модель предметной области и вариант использования уже достаточно ясны, чтобы их можно было раскрыть с помощью HTTP. API подключают команды и запросы к уровню представления через Minimal APIs, контракты, typed responses и метаданные документации.
lino api new lino api new --name <ApiName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino api list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Интерактивный мастер предложит:
- Услуга: сервис, в котором будет создан API.
- Модуль: сервисный модуль, если применимо.
- Сущность или перечисление: элемент домена, связанный с endpoint.
- Имя API: обычно соответствует глаголу операции, например
CreatePerson. - Тип операции:
GET,POST,PUT,PATCH,DELETE, upload, download или endpoint опций endpoint. - Маршрут:шаблон маршрута, например
/people/{id:guid}. - Характеристики: поля запроса и ответа, которые фактически должны пересекать границу HTTP.
Что может настроить мастер
- ПОЛУЧАТЬ: одиночный результат, список, постраничный список и параметры/выбор сценариев.
- ПОЧТА: создание и бизнес-действия, включая тип команды и выбранные свойства.
- ПОМЕЩАТЬ и ПЛАСТЫРЬ: полное или частичное обновление.
- УДАЛИТЬ: удаление сопоставлено с командами удаления.
- Загрузить: endpoints с
IFormFileиDisableAntiforgery()когда это необходимо. - Download: endpoints возвращают
FileStreamHttpResult; Проекты, прошедшие проверку подлинности, могут создавать endpoint токена для безопасного доступа к файлам. - Перечисления: endpoints, которые предоставляют допустимые параметры для каждого сгенерированного запроса и ответа.
Рекомендуемый расход
- Создайте или просмотрите сущность, команды и запросы, которые представляют вариант использования.
- Бегать
lino api newи выберите правильный сервис, модуль и объект. - Выбирайте тип операции в зависимости от варианта использования, а не только по желаемому глаголу HTTP.
- Определите стабильный маршрут, используя такие ограничения, как
{id:int}или{id:guid}когда это уместно. - Выбирайте только те свойства, которые должны пересекать границу HTTP.
- Определите авторизацию, разрешение, требования tenantа, ограничение скорости и ожидаемые коды состояния.
- Запустите сборку и проверьте Scalar/OpenAPI, чтобы подтвердить маршрут, сводку, версию, безопасность и полученные ответы.
Пример: CreatePerson
При создании API POST вызов CreatePerson, связанный с сущностью Person, CLI генерирует endpoint, контракты запроса/ответа, расширения сопоставления, метаданные OpenAPI и интеграцию с соответствующей командой.
<ProjectName>/
└── src/
└── Services/
└── <ServiceName>/
└── Api/
└── Endpoints/
└── People/
└── CreatePerson/
├── CreatePersonEndpoint.cs
├── CreatePersonExtensions.cs
├── CreatePersonRequest.cs
└── CreatePersonResponse.cs
Контракты и typed clients
Если в проекте есть веб-приложение Blazor, Lino также генерирует артефакты для typed consumption API: общие контракты, клиентский интерфейс и реализацию HTTP. Это позволяет Blazor использовать endpoints простым, последовательным и строго типизированным способом.
<ProjectName>/
└── src/
└── Services/
└── <ServiceName>/
├── Api.Contracts/
│ └── Features/
│ └── People/
│ ├── CreatePerson/
│ │ ├── CreatePersonRequest.cs
│ │ └── CreatePersonResponse.cs
│ └── IPersonApiClient.cs
└── Api.Client/
└── Features/
└── PersonApiClient.cs
Клиентский интерфейс зарегистрирован для внедрения зависимостей, и реализация использует HttpClientProvider с помощью помощников Tolitech HTTP для вызова сгенерированного API строго типизированным способом.
Контрольный список перед публикацией
- Использовать
GETдля чтения,POSTдля создания/действий,PUT/PATCHдля перемен иDELETEдля удаления, когда это имеет смысл. - Не предоставляйте объекты домена напрямую как внешний контракт.
- Проверка документа, конфликт, ошибки «не найден» и «отказ в доступе».
- Использовать
api listчтобы избежать дублирования маршрутов или конкурирующих endpoints для одного и того же варианта использования.
Регистрация endpoint с помощью source generators
Lino позволяет избежать ручного сопоставления больших файлов с помощью source generators. Вместо перечисления endpoints одну за другой в Program.cs, журнал создается во время компиляции.
Созданные классы endpoints реализуют IEndpoint из Tolitech.MinimalApis.Generators.Abstractions. Группа endpoints звонит MapEndpointsGenerated(), произведенный Tolitech.MinimalApis.Generators, а новые endpoints регистрируются с помощью сгенерированного кода.
Почему это имеет значение
- Меньше ручной проводки: разработчикам не нужно вручную сопоставлять каждую endpoint.
- Согласованность во время компиляции: endpoints имеют одну и ту же структуру и обнаруживаются сгенерированным кодом.
- Чистый запуск:
Program.csделегирует настройку служб, промежуточного программного обеспечения и методов расширения. - АОТ-совместимость: уменьшает зависимость от отражения во время выполнения.
- Согласованный OpenAPI: теги, сводки, коды состояния и версия генерируются вместе с endpoint.
- Архитектурное выравнивание: HTTP находится в API, оркестровка осуществляется через MediatR, а контракты можно передавать клиентам.
Поток во время выполнения
Program.csсоздает приложение и вызывает расширение из endpoints службы или модуля.- Расширение создает набор версий API и группу endpoints, применяет авторизацию/ограничение скорости и осуществляет вызовы.
MapEndpointsGenerated(). - Сгенерированный картограф вызывает метод
MapEndpointкаждой endpoint. - Каждая endpoint сопоставляет маршрут, метаданные OpenAPI, разрешения, требования клиента и обработчик.
- Обработчик получает входные данные HTTP, преобразует их в команду/запрос, отправляет в MediatR и возвращает typed result.
Определения ошибок
Определения ошибок стандартизируют известные ошибки домена и приложения. Они помогают API, handlers, logs и frontend решать предсказуемые проблемы, не полагаясь на случайные сообщения, повторяющиеся строки или специальные решения в каждой конечной точке.
lino error-definition new --name <ErrorDefinitionName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino error-definition list --service <ServiceName> --module <ModuleName> --entity <EntityName>
В сгенерированных API ожидаемые ошибки, возвращаемые командами и запросами, должны быть преобразованы в ProblemDetails с кодом состояния, кодом ошибки и защищенным сообщением. Сервер может вести подробные технические журналы, но ответ HTTP должен оставаться последовательным, безопасным и локализуемым.
| Статус | Типичное использование | Пример |
|---|---|---|
| 400 неверный запрос | Неверный ввод или ошибка проверки. | Отсутствует обязательное поле, неверный формат, нарушено правило запроса. |
| 401 Несанкционированный | Неаутентифицированный пользователь. | Токен отсутствует, просрочен или недействителен. |
| 403 Запрещено | Аутентифицированный пользователь без разрешения. | Требуется разрешение RequirePermission не предоставлено. |
| 404 Не найден | Несуществующий ресурс или выход за пределы разрешенной области. | ProductNotFound, объект от другого клиента или неизвестный идентификатор. |
| 409 Конфликт | Государственный конфликт или правило уникальности. | Дублирующаяся запись, неверный переход, конфликт версий. |
Передовая практика
- Создайте определения ошибок для ожидаемых и повторно используемых сбоев.
- Не возвращайте клиенту технические исключения или сведения об инфраструктуре.
- Поддерживайте стабильные коды ошибок, чтобы интерфейс, typed clients и тесты могли безопасно реагировать.
- Задокументируйте в OpenAPI коды состояния, которые может создавать endpoint.
- Используйте журналы на стороне сервера для получения диагностических сведений и защищенных сообщений в общедоступных ответах.
