Entwickeln von APIs

APIs sind die HTTP-Grenze eines Lino-Dienstes. Sie stellen AnwendungsfÀlle auf Application layer bereit, ohne Transportbedenken mit DomÀnenregeln zu vermischen. In diesem Kapitel wird erlÀutert, wie Lino Minimal APIs, Request/Response-Contracts, typed clients, OpenAPI-Metadaten und die automatische Registrierung von Endpoints durch Source Generators generiert.


Der generierte Endpoint muss in Ordnung bleiben: Er empfĂ€ngt HTTP-Daten, stellt einen Befehl oder eine Abfrage zusammen und sendet ihn ĂŒber an die Anwendungsschicht ISender und wandelt das Ergebnis in eine typisierte Antwort um. Validierung, GeschĂ€ftsregeln, Persistenz, Transaktionen und DomĂ€nenautorisierung werden in Befehlen, Abfragen, Handlern, Validatoren, Repositorys und Unit of Work fortgesetzt.

Minimal APIs auf Lino

Lino ĂŒbernimmt ASP.NET Core Minimal APIs als Standard fĂŒr die Generierung von Endpoints, da sie den Code direkt, explizit und performant halten, ohne die Grenzen von Clean Architecture zu ĂŒberschreiten.

In aktuellen Lino-Projekten sind generierte Endpoints Minimal API-Klassen, die implementieren IEndpoint. Jeder Endpoint stellt eine statische Methode bereit MapEndpoint(IEndpointRouteBuilder app) und eine Handler-Methode, die verwendet ISender um den generierten Befehl oder die generierte Abfrage an die Anwendungsschicht zu senden.

Hauptteile generiert

  • *Endpoint.cs: Ordnet Methode HTTP, Route, Metadaten, Autorisierung, Tenantsanforderung, Ratenbegrenzung und Version zu.
  • *Request.cs: Stellt Eingaben dar, die aus dem Textkörper, der Abfragezeichenfolge, Routenparametern oder Formulardaten stammen.
  • *Extensions.cs: Konvertiert die Anfrage in einen Befehl/eine Abfrage und konvertiert das Anwendungsergebnis in eine Antwort HTTP.
  • *Response.cs: Definiert den stark typisierten Vertrag, der vom Endpoint und den typisierten Clients zurĂŒckgegeben wird.

Integrierte Funktionen

Lino verwendet TypedResults Und Results<...> sodass Erfolgs- und Fehlerantworten im Code explizit sind und in OpenAPI korrekt angezeigt werden. Von der Anwendungsschicht kommende Fehler werden konvertiert ProblemDetails setzen result.MapToProblemDetails().

  • WithTags: Gruppiert Endpoints nach Modul, EntitĂ€t oder Feature in OpenAPI und Scalar.
  • WithName: Legt gegebenenfalls eine konsistente operationId fest.
  • WithSummary: Beschreibt klar den Zweck des Endpoints.
  • Produces(statusCode, schema): Gibt Statuscodes und AntwortvertrĂ€ge an.
  • MapToApiVersion(1, 0): Ordnet den Endpoint der API-Version zu.
  • RequirePermission, RequireAuthorization, AllowAnonymous Und RequireTenant: Sicherheit entsprechend den Projektoptionen anwenden.
  • Ratenbegrenzung auf Gruppen- oder Endpointsbene unter Verwendung authentifizierter oder anonymer Richtlinien je nach Konfiguration.

Anfragen und Antworten

StandardmĂ€ĂŸig verwendet Lino Aufzeichnungen fĂŒr Anfragen und Antworten. Sie sind prĂ€gnant, standardmĂ€ĂŸig unverĂ€nderlich und funktionieren gut als explizite VertrĂ€ge zwischen API, typisierten Kunden und externen Verbrauchern.

  • Über den Endpoint empfangene Anfragen werden in Befehle oder Abfragen umgewandelt.
  • Ergebnisse von Befehlen oder Abfragen werden in Antworten umgewandelt.
  • DomĂ€nenentitĂ€ten sollten nicht direkt als Vertrag HTTP verfĂŒgbar gemacht werden.
public record CreatePersonRequest(string Name, int Age);
public record CreatePersonResponse(Guid Id, string Name, int Age);

Erstellen neuer APIs

Erstellen Sie APIs durch CLI, wenn das DomĂ€nenmodell und der Anwendungsfall bereits klar genug sind, um durch HTTP verfĂŒgbar gemacht zu werden. APIs verbinden Commands und Queries ĂŒber Minimal APIs, VertrĂ€ge, typisierte Antworten und Dokumentationsmetadaten mit der PrĂ€sentationsschicht.

lino api new
lino api new --name <ApiName> --service <ServiceName> --module <ModuleName> --entity <EntityName>
lino api list --service <ServiceName> --module <ModuleName> --entity <EntityName>

Der interaktive Assistent fordert Sie auf:

  • Service: Dienst, in dem API erstellt wird.
  • Modul: Servicemodul, falls zutreffend.
  • EntitĂ€t oder AufzĂ€hlung: DomĂ€nenelement, das dem Endpoint zugeordnet ist.
  • Name von API: Normalerweise ausgerichtet auf das Verb der Operation, z. B CreatePerson.
  • Art der Operation: GET, POST, PUT, PATCH, DELETE, Upload, Download oder Endpointoptionen.
  • Route:Routenmuster, wie /people/{id:guid}.
  • Eigenschaften: Anforderungs- und Antwortfelder, die tatsĂ€chlich die HTTP-Grenze ĂŒberschreiten mĂŒssen.

Was der Assistent konfigurieren kann

  • ERHALTEN: Einzelergebnis, Liste, Seitenliste und Optionen/Szenarien auswĂ€hlen.
  • POST: Erstellungs- und GeschĂ€ftsaktionen, einschließlich Befehlstyp und ausgewĂ€hlte Eigenschaften.
  • SETZEN Und PATCH: vollstĂ€ndige oder teilweise Aktualisierung.
  • LÖSCHEN: Entfernung zugeordnet, um Befehle zu löschen.
  • Hochladen: Endpoints mit IFormFile Und DisableAntiforgery() wenn nötig.
  • Herunterladen:Endpoints zurĂŒckgeben FileStreamHttpResult; Authentifizierte Projekte können einen Token-Endpoint fĂŒr sicheren Dateizugriff generieren.
  • AufzĂ€hlungen: Endpoints, die gĂŒltige Optionen pro generierter Abfrage und Antwort bereitstellen.

Empfohlener Durchfluss

  1. Erstellen oder ĂŒberprĂŒfen Sie die EntitĂ€t, Commands und Queries, die den Anwendungsfall darstellen.
  2. Laufen lino api new und wÀhlen Sie den richtigen Dienst, das richtige Modul und die richtige EntitÀt aus.
  3. WĂ€hlen Sie den Operationstyp nach Anwendungsfall und nicht nur nach dem gewĂŒnschten HTTP-Verb.
  4. Definieren Sie eine stabile Route unter Verwendung von EinschrÀnkungen wie {id:int} oder {id:guid} wenn es angebracht ist.
  5. WĂ€hlen Sie nur Eigenschaften aus, die die HTTP-Grenze ĂŒberschreiten mĂŒssen.
  6. Definieren Sie Autorisierung, Erlaubnis, Mieteranforderungen, Ratenbegrenzung und erwartete Statuscodes.
  7. FĂŒhren Sie Build aus und ĂŒberprĂŒfen Sie Scalar/OpenAPI, um Route, Zusammenfassung, Version, Sicherheit und erzeugte Antworten zu bestĂ€tigen.

Beispiel: CreatePerson

Beim Erstellen eines API POST Anruf CreatePerson, mit der EntitÀt verbunden Person, CLI generiert Endpoints, Anforderungs-/AntwortvertrÀge, Zuordnungserweiterungen, OpenAPI-Metadaten und die Integration mit dem entsprechenden Befehl.

<ProjectName>/
└── src/
    └── Services/
        └── <ServiceName>/
            └── Api/
                └── Endpoints/
                    └── People/
                        └── CreatePerson/
                            ├── CreatePersonEndpoint.cs
                            ├── CreatePersonExtensions.cs
                            ├── CreatePersonRequest.cs
                            └── CreatePersonResponse.cs

VertrÀge und typisierte Kunden

Wenn das Projekt ĂŒber eine Web-App Blazor verfĂŒgt, generiert Lino auch Artefakte fĂŒr die typisierte Nutzung von APIs: gemeinsame VertrĂ€ge, Client-Schnittstelle und HTTP-Implementierung. Dadurch kann Blazor Endpoints auf einfache, konsistente und stark typisierte Weise nutzen.

<ProjectName>/
└── src/
    └── Services/
        └── <ServiceName>/
            ├── Api.Contracts/
            │   └── Features/
            │       └── People/
            │           ├── CreatePerson/
            │           │   ├── CreatePersonRequest.cs
            │           │   └── CreatePersonResponse.cs
            │           └── IPersonApiClient.cs
            └── Api.Client/
                └── Features/
                    └── PersonApiClient.cs

Die Client-Schnittstelle ist fĂŒr die AbhĂ€ngigkeitsinjektion registriert und wird von der Implementierung verwendet HttpClientProvider mit den HTTP-Helfern von Tolitech, um das generierte API auf stark typisierte Weise aufzurufen.

Checkliste vor der Veröffentlichung

  • Verwenden GET zum Lesen, POST fĂŒr Schöpfung/Aktionen, PUT/PATCH fĂŒr VerĂ€nderung und DELETE zum Entfernen, wenn es sinnvoll ist.
  • Stellen Sie DomĂ€nenentitĂ€ten nicht direkt als externen Vertrag bereit.
  • Fehler bei Dokumentvalidierung, Konflikt, nicht gefunden und Zugriff verweigert.
  • Verwenden api list um doppelte Routen oder konkurrierende Endpoints fĂŒr denselben Anwendungsfall zu vermeiden.

Endpointregistrierung mit Source Generators

Lino vermeidet die manuelle Zuordnung großer Dateien mithilfe von Source Generators. Anstatt die Endpoints einzeln aufzulisten Program.cs, das Protokoll wird wĂ€hrend der Kompilierung erstellt.

Generierte Endpointklassen werden implementiert IEndpoint von Tolitech.MinimalApis.Generators.Abstractions. Die Endpointgruppenanrufe MapEndpointsGenerated(), produziert von Tolitech.MinimalApis.Generatorsund neue Endpoints werden durch generierten Code registriert.

Warum ist das wichtig?

  • Weniger manuelle Verkabelung: Entwickler mĂŒssen nicht daran denken, jeden Endpoint manuell zuzuordnen.
  • Konsistenz zur Kompilierungszeit: Endpoints folgen derselben Struktur und werden durch generierten Code erkannt.
  • Saubererer Start: Program.cs Delegiert das Setup fĂŒr die Konfiguration von Diensten, Middleware und Erweiterungsmethoden.
  • AOT-KompatibilitĂ€t: Reduziert die AbhĂ€ngigkeit von der Reflexion zur Laufzeit.
  • OpenAPI konsistent: Tags, Zusammenfassungen, Statuscodes und Version werden am Endpoint generiert.
  • Architektonische Ausrichtung: HTTP befindet sich in API, die Orchestrierung erfolgt ĂŒber MediatR und VertrĂ€ge können mit Kunden geteilt werden.

Fluss zur Laufzeit

  1. Program.cs erstellt die Anwendung und ruft die Erweiterung von den Dienst- oder Modulendpunkten aus auf.
  2. Die Erweiterung erstellt den API-Versionssatz und die Endpointgruppe, wendet Autorisierung/Ratenbegrenzung und Aufrufe an MapEndpointsGenerated().
  3. Der generierte Mapper ruft die Methode auf MapEndpoint jedes Endpoints.
  4. Jeder Endpoint ordnet Route, OpenAPI-Metadaten, Berechtigungen, Tenantsanforderungen und Handler zu.
  5. Der Handler empfĂ€ngt die Eingabe HTTP, wandelt sie in einen Befehl/eine Abfrage um, sendet sie an MediatR und gibt ein typisiertes Ergebnis zurĂŒck.

Fehlerdefinitionen

Fehlerdefinitionen standardisieren bekannte DomĂ€nen- und Anwendungsfehler. Sie helfen APIs, Handlern, Protokollen und Frontends, vorhersehbare Probleme zu bewĂ€ltigen, ohne sich auf vereinzelte Nachrichten, doppelte Zeichenfolgen oder Ad-hoc-Entscheidungen an jedem Endpoint verlassen zu mĂŒssen.

lino error-definition new --name <ErrorDefinitionName> --service <ServiceName> --module <ModuleName> --entity <EntityName>
lino error-definition list --service <ServiceName> --module <ModuleName> --entity <EntityName>

In generierten APIs mĂŒssen erwartete Fehler, die von Befehlen und Abfragen zurĂŒckgegeben werden, konvertiert werden ProblemDetails mit Statuscode, Fehlercode und sicherer Nachricht. Der Server kann detaillierte technische Protokolle aufzeichnen, aber die HTTP-Antwort muss konsistent, sicher und lokalisierbar bleiben.

StatusTypische VerwendungBeispiel
400 UngĂŒltige AnfrageUngĂŒltige Eingabe oder Validierungsfehler.Fehlendes Pflichtfeld, ungĂŒltiges Format, fehlerhafte Anforderungsregel.
401 Nicht autorisiertNicht authentifizierter Benutzer.Fehlendes, abgelaufenes oder ungĂŒltiges Token.
403 VerbotenAuthentifizierter Benutzer ohne Erlaubnis.Genehmigung erforderlich von RequirePermission nicht gewÀhrt.
404 Nicht gefundenNicht vorhandene Ressource oder außerhalb des zulĂ€ssigen Bereichs.ProductNotFound, EntitĂ€t von einem anderen Tenants oder unbekannte Kennung.
409 KonfliktStaatskonflikt oder Einzigartigkeitsregel.Doppelter Datensatz, ungĂŒltiger Übergang, Versionskonflikt.

Gute Praktiken

  • Erstellen Sie Fehlerdefinitionen fĂŒr erwartete und wiederverwendbare Fehler.
  • Vermeiden Sie die RĂŒckgabe technischer Ausnahmen oder Infrastrukturdetails an den Kunden.
  • Sorgen Sie fĂŒr stabile Fehlercodes, damit Frontend, typed clients und Tests sicher reagieren können.
  • Dokumentieren Sie in OpenAPI die Statuscodes, die der Endpoint erzeugen kann.
  • Verwenden Sie serverseitige Protokolle fĂŒr Diagnosedetails und sichere Nachrichten in öffentlichen Antworten.
Ein unbehandelter Fehler ist aufgetreten. Aktualisieren 🗙