Desarrollo de API
Las APIs son el límite HTTP de un servicio Lino. Exponen casos de uso de la capa de aplicación sin mezclar preocupaciones de transporte con reglas de dominio. Este capítulo explica cómo Lino genera Minimal APIs, contratos de solicitud/respuesta, typed clients, metadatos OpenAPI y registro automático de endpoints por parte de los source generators.
El endpoint generado debe mantenerse delgado: recibe datos HTTP, ensambla un comando o consulta, lo envía a la capa de aplicación a través de ISender y convierte el resultado en una respuesta tipada. La validación, las reglas de negocio, la persistencia, las transacciones y la autorización de dominio continúan en comandos, consultas, manejadores, validadores, repositorios y Unit of Work.
Minimal APIs en Lino
Lino adopta el núcleo ASP.NET Minimal APIs como estándar para generar endpoints, porque mantienen el código directo, explícito y funcional sin romper los límites de Clean Architecture.
En los proyectos actuales Lino, los endpoints generados son clases de Minimal API que implementan IEndpoint. Cada endpoint expone un método estático MapEndpoint(IEndpointRouteBuilder app) y un método handler que utiliza ISender para enviar el comando o consulta generado a la capa de Aplicación.
Partes principales generadas
*Endpoint.cs: mapea el método HTTP, ruta, metadatos, autorización, tenant requirement, rate limiting y versión.*Request.cs: representa la entrada proveniente del cuerpo, cadena de consulta, parámetros de ruta o datos del formulario.*Extensions.cs: convierte la request en command/query y convierte el resultado de la aplicación en respuesta HTTP.*Response.cs: define el contrato fuertemente tipado devuelto por el endpoint y los typed clients.
Funciones integradas
Lino usa TypedResults y Results<...> para que las respuestas de éxito y error sean explícitas en el código y aparezcan correctamente en OpenAPI. Las fallas provenientes de la capa de Aplicación se convierten en ProblemDetails mediante result.MapToProblemDetails().
WithTags: Agrupa endpoints por módulo, entidad o característica en OpenAPI y Scalar.WithName: establece un ID de operación coherente cuando corresponda.WithSummary: describe claramente el propósito del endpoint.Produces(statusCode, schema): especifica códigos de estado y contratos de respuesta.MapToApiVersion(1, 0): asocia el endpoint con la versión API.RequirePermission,RequireAuthorization,AllowAnonymousyRequireTenant: aplicar seguridad según las opciones del proyecto.- Limitación de velocidad a nivel de grupo o endpoint, utilizando políticas autenticadas o anónimas según la configuración.
Solicitudes y respuestas
Por defecto, Lino usa records para requests y responses. Son concisos, inmutables por defecto y funcionan bien como contratos explícitos entre API, typed clients y consumidores externos.
- Las solicitudes recibidas a través del endpoint se transforman en Commands o Queries.
- Los resultados de los commands o queries se convierten en respuestas.
- Las entidades de dominio no deben exponerse directamente como contrato HTTP.
public record CreatePersonRequest(string Name, int Age); public record CreatePersonResponse(Guid Id, string Name, int Age);
Creando nuevos API
Cree API mediante CLI cuando el modelo de dominio y el caso de uso ya sean lo suficientemente claros como para ser expuestos por HTTP. Las APIs conectan comandos y consultas a la capa de presentación a través de Minimal APIs, contratos, respuestas tipadas y metadatos de documentación.
lino api new lino api new --name <ApiName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino api list --service <ServiceName> --module <ModuleName> --entity <EntityName>
El asistente interactivo le preguntará:
- Servicio: servicio en el que se creará API.
- Módulo: módulo de servicio, cuando corresponda.
- Entidad o enumeración: elemento de dominio asociado con el endpoint.
- Nombre de API: normalmente alineado con el verbo de la operación, como
CreatePerson. - Tipo de operación:
GET,POST,PUT,PATCH,DELETE, carga, descarga o opciones de endpoint. - Ruta: patrón de ruta, como
/people/{id:guid}. - Propiedades: campos de solicitud y respuesta que realmente deben cruzar el límite HTTP.
Qué puede configurar el asistente
- CONSEGUIR: resultado único, lista, lista paginada y opciones/escenarios seleccionados.
- CORREO: creación y acciones comerciales, incluido el tipo de comando y las propiedades seleccionadas.
- PONER y PARCHE: actualización completa o parcial.
- BORRAR: eliminación asignada para eliminar comandos.
- Subir: endpoints con
IFormFileyDisableAntiforgery()cuando sea necesario. - Descargar: endpoints que retornan
FileStreamHttpResult; los proyectos autenticados pueden generar un endpoint de token para un acceso seguro a los archivos. - Enumeraciones: endpoints que exponen opciones válidas por consulta y respuesta generadas.
Flujo recomendado
- Cree o revise la entidad, los comandos y las consultas que representan el caso de uso.
- Correr
lino api newy seleccione el servicio, módulo y entidad correctos. - Elija el tipo de operación por caso de uso, no solo por el verbo HTTP deseado.
- Defina una ruta estable, utilizando restricciones como
{id:int}o{id:guid}cuando sea apropiado. - Seleccione solo las propiedades que deben cruzar el límite HTTP.
- Defina autorización, permiso, requisitos de inquilino, limitación de tarifas y códigos de estado esperado.
- Ejecute la compilación e inspeccione Scalar/OpenAPI para confirmar la ruta, el resumen, la versión, la seguridad y las respuestas producidas.
Ejemplo: crear persona
Al crear un API POST llamar CreatePerson, asociado a la entidad Person, CLI genera endpoints, contratos de solicitud/respuesta, extensiones de mapeo, metadatos OpenAPI e integración con el comando correspondiente.
<ProjectName>/
└── src/
└── Services/
└── <ServiceName>/
└── Api/
└── Endpoints/
└── People/
└── CreatePerson/
├── CreatePersonEndpoint.cs
├── CreatePersonExtensions.cs
├── CreatePersonRequest.cs
└── CreatePersonResponse.cs
Contratos y typed clients
Cuando el proyecto tiene una Web App Blazor, Lino también genera artefactos para el consumo tipificado de API: contratos compartidos, interfaz de cliente e implementación de HTTP. Esto permite a Blazor consumir endpoints de una manera simple, consistente y fuertemente tipada.
<ProjectName>/
└── src/
└── Services/
└── <ServiceName>/
├── Api.Contracts/
│ └── Features/
│ └── People/
│ ├── CreatePerson/
│ │ ├── CreatePersonRequest.cs
│ │ └── CreatePersonResponse.cs
│ └── IPersonApiClient.cs
└── Api.Client/
└── Features/
└── PersonApiClient.cs
La interfaz del cliente está registrada para la inyección de dependencia y la implementación utiliza HttpClientProvider con los ayudantes HTTP de Tolitech para llamar al API generado de forma inflexible.
Lista de verificación antes de publicar
- Usar
GETpara leer,POSTpara creación/acciones,PUT/PATCHpor el cambio yDELETEpara su eliminación cuando tenga sentido. - No exponga entidades de dominio directamente como un contrato externo.
- Errores de validación de documentos, conflictos, no encontrados y acceso denegado.
- Usar
api listpara evitar rutas duplicadas o endpoints competitivos para el mismo caso de uso.
Registro de terminales con source generators
Lino evita mapear manualmente archivos grandes usando source generators. En lugar de enumerar los endpoints uno por uno en Program.cs, el registro se genera durante la compilación.
Implementación de clases de endpoint generadas IEndpoint de Tolitech.MinimalApis.Generators.Abstractions. Las llamadas del grupo de terminales MapEndpointsGenerated(), producido por Tolitech.MinimalApis.Generatorsy los nuevos endpoints se registran mediante el código generado.
¿Por qué esto importa?
- Menos wiring manual: Los desarrolladores no necesitan recordar asignar cada endpoint manualmente.
- Coherencia en tiempo de compilación: los endpoints siguen la misma estructura y se descubren mediante el código generado.
- Inicio más limpio:
Program.csdelega la configuración para configurar servicios, middleware y métodos de extensión. - Compatibilidad AOT: reduce la dependencia de la reflexión en tiempo de ejecución.
- OpenAPI consistente: las etiquetas, resúmenes, códigos de estado y versión se generan en el endpoint.
- Alineación arquitectónica: HTTP está en API, la orquestación pasa por MediatR y los contratos se pueden compartir con los clientes.
Flujo en tiempo de ejecución
Program.csconstruye la aplicación y llama a la extensión desde los endpoints del servicio o módulo.- La extensión crea el conjunto de versiones API y el grupo de terminales, aplica autorización/rate limiting y llamadas
MapEndpointsGenerated(). - El asignador generado llama al método.
MapEndpointde cada endpoint. - Cada endpoint asigna la ruta, los metadatos OpenAPI, el permiso, los requisitos del inquilino y el controlador.
- El controlador recibe la entrada HTTP, la convierte en comando/consulta, la envía a MediatR y devuelve un resultado escrito.
Definiciones de errores
Las definiciones de errores estandarizan los fallos conocidos de dominios y aplicaciones. Ayudan a las APIs, handlers, registros y interfaces a manejar problemas predecibles sin depender de mensajes perdidos, cadenas duplicadas o decisiones ad hoc en cada endpoint.
lino error-definition new --name <ErrorDefinitionName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino error-definition list --service <ServiceName> --module <ModuleName> --entity <EntityName>
En las APIs generados, los fallos esperados devueltos por comandos y consultas se deben convertir a ProblemDetails con código de estado, código de error y mensaje seguro. El servidor puede registrar logs técnicos detallados, pero la respuesta HTTP debe permanecer consistente, segura y localizable.
| Estado | Uso típico | Ejemplo |
|---|---|---|
| 400 Solicitud incorrecta | Entrada no válida o error de validación. | Falta un campo obligatorio, formato no válido, regla de solicitud incumplida. |
| 401 No autorizado | Usuario no autenticado. | Token faltante, caducado o no válido. |
| 403 Prohibido | Usuario autenticado sin permiso. | Permiso requerido por RequirePermission no concedido. |
| 404 no encontrado | Recurso inexistente o fuera del alcance permitido. | ProductNotFound, entidad de otro inquilino o identificador desconocido. |
| 409 Conflicto | Conflicto de estados o regla de unicidad. | Registro duplicado, transición no válida, conflicto de versiones. |
Buenas practicas
- Cree definiciones de errores para fallas esperadas y reutilizables.
- Evite devolver excepciones técnicas o detalles de infraestructura al cliente.
- Mantenga códigos de error estables para que la interfaz, los typed clients y las pruebas puedan reaccionar de forma segura.
- Documente en OpenAPI los códigos de estado que puede producir el endpoint.
- Utilice logs del servidor para obtener detalles de diagnóstico y mensajes seguros en la respuesta pública.
