Développement de API
Les APIs constituent la limite HTTP d'un service Lino. Elles exposent des cas d'utilisation de la couche application sans mélanger les problÚmes de transport avec les rÚgles de domaine. Ce chapitre explique comment Lino génÚre des Minimal APIs, des contrats request/response, des typed clients, des métadonnées OpenAPI et l'enregistrement automatique des endpoints par les source generators.
Le endpoint gĂ©nĂ©rĂ© doit rester correct : reçoit les donnĂ©es HTTP, assemble une commande ou une requĂȘte, l'envoie Ă la couche Application via ISender et convertit le rĂ©sultat en une rĂ©ponse tapĂ©e. La validation, les rĂšgles mĂ©tier, la persistance, les transactions et l'autorisation de domaine se poursuivent dans les commandes, les requĂȘtes, les gestionnaires, les validateurs, les rĂ©fĂ©rentiels et l'unitĂ© de travail.
API minimes sur Lino
Lino adopte le noyau ASP.NET API minimes comme standard pour générer des endpoints, car ils gardent le code direct, explicite et performant sans briser les limites de Clean Architecture.
Dans les projets Lino actuels, les endpoints gĂ©nĂ©rĂ©s sont des classes minimales API qui implĂ©mentent IEndpoint. Chaque endpoint expose une mĂ©thode statique MapEndpoint(IEndpointRouteBuilder app) et une mĂ©thode de gestionnaire qui utilise ISender pour distribuer la commande ou la requĂȘte gĂ©nĂ©rĂ©e Ă la couche Application.
PiÚces principales générées
*Endpoint.cs: mĂ©thode de cartes HTTP, itinĂ©raire, mĂ©tadonnĂ©es, autorisation, exigences du tenant, limitation de dĂ©bit et version.*Request.cs: reprĂ©sente une entrĂ©e provenant du corps, de la chaĂźne de requĂȘte, des paramĂštres de route ou des donnĂ©es de formulaire.*Extensions.cs: convertit la requĂȘte en commande/requĂȘte et convertit le rĂ©sultat de l'application en rĂ©ponse HTTP.*Response.cs: dĂ©finit le contrat fortement typĂ© renvoyĂ© par le endpoint et les typed clients.
Fonctionnalités intégrées
Lino utilise TypedResults et Results<...> afin que les réponses de réussite et d'erreur soient explicites dans le code et apparaissent correctement dans OpenAPI. Les défauts provenant de la couche Application sont convertis en ProblemDetails mettre result.MapToProblemDetails().
WithTags: regroupe les endpoints par module, entité ou fonctionnalité dans OpenAPI et Scalar.WithName: définit un identifiant d'opération cohérent, le cas échéant.WithSummary: décrit clairement l'objectif du endpoint.Produces(statusCode, schema): spécifie les codes d'état et les contrats de réponse.MapToApiVersion(1, 0): associe le endpoint à la version API.RequirePermission,RequireAuthorization,AllowAnonymousetRequireTenant: appliquer la sécurité selon les options du projet.- Limitation du débit au niveau du groupe ou du endpoint, à l'aide de politiques authentifiées ou anonymes selon la configuration.
Demandes et réponses
Par défaut, Lino utilise enregistrements pour les demandes et les réponses. Ils sont concis, immuables par défaut et fonctionnent bien en tant que contrats explicites entre API, les typed clients et les consommateurs externes.
- Les requĂȘtes reçues via le endpoint sont transformĂ©es en commandes ou requĂȘtes.
- Les rĂ©sultats des commandes ou des requĂȘtes sont convertis en rĂ©ponses.
- Les entitĂ©s de domaine ne doivent pas ĂȘtre directement exposĂ©es en tant que contrat HTTP.
public record CreatePersonRequest(string Name, int Age); public record CreatePersonResponse(Guid Id, string Name, int Age);
Création de nouveaux API
CrĂ©ez des API par CLI lorsque le modĂšle de domaine et le cas d'utilisation sont dĂ©jĂ suffisamment clairs pour ĂȘtre exposĂ©s par HTTP. Les API connectent les commandes et les requĂȘtes Ă la couche de prĂ©sentation via des Minimal APIs, des contrats, des rĂ©ponses saisies et des mĂ©tadonnĂ©es de documentation.
lino api new lino api new --name <ApiName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino api list --service <ServiceName> --module <ModuleName> --entity <EntityName>
L'assistant interactif vous demandera :
- Service: service dans lequel API sera créé.
- Module: module de service, le cas échéant.
- Entité ou énumération: élément de domaine associé au endpoint.
- Nom de API: normalement aligné avec le verbe de l'opération, tel que
CreatePerson. - Type d'opération:
GET,POST,PUT,PATCH,DELETE, options de chargement, de téléchargement ou de endpoint. - Itinéraire:modÚle d'itinéraire, comme
/people/{id:guid}. - PropriĂ©tĂ©s: champs de requĂȘte et de rĂ©ponse qui doivent effectivement traverser la frontiĂšre HTTP.
Ce que l'assistant peut configurer
- OBTENIR: résultat unique, liste, liste paginée et options/sélectionner des scénarios.
- POSTE: création et actions commerciales, y compris le type de commande et les propriétés sélectionnées.
- METTRE et CORRECTIF: mise Ă jour complĂšte ou partielle.
- SUPPRIMER: suppression mappée pour supprimer les commandes.
- Télécharger: endpoints avec
IFormFileetDisableAntiforgery()lorsque cela est nécessaire. - Télécharger:retour des endpoints
FileStreamHttpResult; Les projets authentifiĂ©s peuvent gĂ©nĂ©rer un endpoint de jeton pour un accĂšs sĂ©curisĂ© aux fichiers. - ĂnumĂ©rations: endpoints qui exposent des options valides par requĂȘte et rĂ©ponse gĂ©nĂ©rĂ©es.
Débit recommandé
- CrĂ©ez ou examinez l'entitĂ©, les commandes et les requĂȘtes qui reprĂ©sentent le cas d'utilisation.
- Courir
lino api newet sélectionnez le service, le module et l'entité corrects. - Choisissez le type d'opération par cas d'utilisation, pas seulement par le verbe HTTP souhaité.
- Définir un itinéraire stable, en utilisant des contraintes telles que
{id:int}ou{id:guid}le cas échéant. - Sélectionnez uniquement les propriétés qui doivent traverser la limite HTTP.
- DĂ©finissez lâautorisation, la permission, les exigences du tenant, la limitation du dĂ©bit et les codes dâĂ©tat attendus.
- Exécutez build et inspectez Scalar/OpenAPI pour confirmer l'itinéraire, le résumé, la version, la sécurité et les réponses produites.
Exemple : Créer une personne
Lors de la création d'un API POST appel CreatePerson, associé à l'entité Person, CLI génÚre un endpoint, des contrats de demande/réponse, des extensions de mappage, des métadonnées OpenAPI et une intégration avec la commande correspondante.
<ProjectName>/
âââ src/
âââ Services/
âââ <ServiceName>/
âââ Api/
âââ Endpoints/
âââ People/
âââ CreatePerson/
âââ CreatePersonEndpoint.cs
âââ CreatePersonExtensions.cs
âââ CreatePersonRequest.cs
âââ CreatePersonResponse.cs
Contrats et typed clients
Lorsque le projet dispose d'une Web App Blazor, Lino génÚre également des artefacts pour la consommation typée des API: contrats partagés, interface client et implémentation de HTTP. Cela permet à Blazor de consommer les endpoints d'une maniÚre simple, cohérente et fortement typée.
<ProjectName>/
âââ src/
âââ Services/
âââ <ServiceName>/
âââ Api.Contracts/
â âââ Features/
â âââ People/
â âââ CreatePerson/
â â âââ CreatePersonRequest.cs
â â âââ CreatePersonResponse.cs
â âââ IPersonApiClient.cs
âââ Api.Client/
âââ Features/
âââ PersonApiClient.cs
L'interface client est enregistrée pour l'injection de dépendances et l'implémentation utilise HttpClientProvider avec les assistants HTTP de Tolitech pour appeler le API généré d'une maniÚre fortement typée.
Liste de contrĂŽle avant de publier
- Utiliser
GETpour la lecture,POSTpour la création/actions,PUT/PATCHpour le changement etDELETEpour le retrait lorsque cela a du sens. - N'exposez pas les entités de domaine directement en tant que contrat externe.
- Erreurs de validation de document, de conflit, d'introuvable et d'accÚs refusé.
- Utiliser
api listpour Ă©viter les routes en double ou les endpoints concurrents pour le mĂȘme cas d'utilisation.
Enregistrement des endpoints avec les source generators
Lino évite de mapper manuellement des fichiers volumineux à l'aide de source generators. Au lieu de lister les endpoints un par un dans Program.cs, l'enregistrement est produit lors de la compilation.
Implémentation des classes de endpoints générées IEndpoint de Tolitech.MinimalApis.Generators.Abstractions. Le groupe de endpoints appelle MapEndpointsGenerated(), produit par Tolitech.MinimalApis.Generators, et les nouveaux endpoints sont enregistrés par le code généré.
Pourquoi est-ce important
- Moins de cùblage manuel: Les développeurs n'ont pas besoin de penser à mapper chaque endpoint manuellement.
- CohĂ©rence au moment de la compilation: les endpoints suivent la mĂȘme structure et sont dĂ©couverts par le code gĂ©nĂ©rĂ©.
- Démarrage plus propre:
Program.csdélÚgue l'installation pour la configuration des services, des middlewares et des méthodes d'extension. - Compatibilité AOT: réduit la dépendance à la réflexion au moment de l'exécution.
- OpenAPI cohérent: les balises, les résumés, les codes d'état et la version sont générés au niveau du point final.
- Alignement architectural: HTTP est dans API, l'orchestration passe par MediatR, et les contrats peuvent ĂȘtre partagĂ©s avec les clients.
Flux au moment de l'exécution
Program.csconstruit l'application et appelle l'extension à partir des endpoints du service ou du module.- L'extension crée l'ensemble de versions API et le groupe de endpoints, applique l'autorisation/limitation de débit et appelle
MapEndpointsGenerated(). - Le mappeur généré appelle la méthode
MapEndpointde chaque point final. - Chaque endpoint mappe l'itinéraire, les métadonnées OpenAPI, l'autorisation, les exigences du tenant et le gestionnaire.
- Le gestionnaire reçoit l'entrĂ©e HTTP, la convertit en commande/requĂȘte, l'envoie Ă MediatR et renvoie un rĂ©sultat typĂ©.
Définitions des erreurs
Les définitions d'erreurs normalisent les erreurs connues du domaine et de l'application. Ils aident les API, les gestionnaires, les journaux et les interfaces à gérer des problÚmes prévisibles sans compter sur des messages parasites, des chaßnes en double ou des décisions ad hoc à chaque endpoint.
lino error-definition new --name <ErrorDefinitionName> --service <ServiceName> --module <ModuleName> --entity <EntityName> lino error-definition list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Dans les API gĂ©nĂ©rĂ©s, les Ă©checs attendus renvoyĂ©s par les commandes et les requĂȘtes doivent ĂȘtre convertis en ProblemDetails avec code d'Ă©tat, code d'erreur et message sĂ©curisĂ©. Le serveur peut enregistrer des journaux techniques dĂ©taillĂ©s, mais la rĂ©ponse HTTP doit rester cohĂ©rente, sĂ©curisĂ©e et localisable.
| Statut | Utilisation typique | Exemple |
|---|---|---|
| 400 requĂȘtes incorrectes | Erreur de saisie ou de validation invalide. | Champ obligatoire manquant, format non valide, rĂšgle de demande non respectĂ©e. |
| 401 Non autorisé | Utilisateur non authentifié. | Jeton manquant, expiré ou invalide. |
| 403 Interdit | Utilisateur authentifié sans autorisation. | Autorisation requise par RequirePermission pas accordé. |
| 404 introuvable | Ressource inexistante ou hors du pĂ©rimĂštre autorisĂ©. | ProductNotFound, entitĂ© dâun autre tenant ou identifiant inconnu. |
| 409 Conflit | Conflit dâĂ©tat ou rĂšgle dâunicitĂ©. | Enregistrement en double, transition invalide, conflit de version. |
Bonnes pratiques
- Créez des définitions d'erreur pour les échecs attendus et réutilisables.
- Ăvitez de renvoyer des exceptions techniques ou des dĂ©tails dâinfrastructure au client.
- Maintenez des codes d'erreur stables afin que le frontend, les clients saisis et les tests puissent réagir en toute sécurité.
- Documentez dans OpenAPI les codes d'état que le endpoint peut produire.
- Utilisez les journaux cÎté serveur pour les détails de diagnostic et les messages sécurisés dans la réponse publique.
