API の開発
API ã¯ãLino ãµãŒãã¹ã® HTTP å¢çã§ãããããã¯ããã©ã³ã¹ããŒãã®åé¡ãšãã¡ã€ã³ ã«ãŒã«ãæ··åããããšãªããã¢ããªã±ãŒã·ã§ã³å±€ã®ãŠãŒã¹ã±ãŒã¹ãå ¬éããŸãããã®ç« ã§ã¯ãLino ãMinimal APIsãrequest/response contractsãtyped clientsãOpenAPI ã¡ã¿ããŒã¿ãããã³Source Generatorsã«ããendpointã®èªåç»é²ãçæããæ¹æ³ã«ã€ããŠèª¬æããŸãã
çæãããendpointã¯æ£åžžãªç¶æ
ãç¶æããå¿
èŠããããŸããHTTP ããŒã¿ãåä¿¡ããã³ãã³ããŸãã¯ã¯ãšãªãçµã¿ç«ãŠããããã¢ããªã±ãŒã·ã§ã³å±€ã«éä¿¡ããŸãã ISender ãããŠçµæãåä»ãã¬ã¹ãã³ã¹ã«å€æããŸããæ€èšŒãããžãã¹ ã«ãŒã«ãæ°žç¶æ§ããã©ã³ã¶ã¯ã·ã§ã³ããã¡ã€ã³èªèšŒã¯ãã³ãã³ããã¯ãšãªããã³ãã©ãŒãããªããŒã¿ãŒããªããžããªãããã³äœæ¥åäœã§ç¶ç¶ãããŸãã
Lino äžã®Minimal APIs
Linoã¯ASP.NETã³ã¢ãæ¡çš Minimal APIs Clean Architecture ã®å¢çãå£ãããšãªããã³ãŒããçŽæ¥çãæç€ºçããã€ããã©ãŒãã³ã¹ã«ä¿ã€ãããendpointãçæããããã®æšæºãšããŠäœ¿çšãããŸãã
çŸåšã® Lino ãããžã§ã¯ãã§ã¯ãçæãããendpointã¯ãå®è£
ããMinimal APIs ã¯ã©ã¹ã§ãã 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: OpenAPI ããã³ Scalar ã®ã¢ãžã¥ãŒã«ããšã³ãã£ãã£ããŸãã¯æ©èœããšã«endpointãã°ã«ãŒãåããŸããWithName: 該åœããå Žåãäžè²«ããoperationIdãèšå®ããŸããWithSummary: endpointã®ç®çãæç¢ºã«èª¬æããŠããŸããProduces(statusCode, schema): ã¹ããŒã¿ã¹ ã³ãŒããšå¿çã³ã³ãã©ã¯ããæå®ããŸããMapToApiVersion(1, 0): endpointã API ããŒãžã§ã³ã«é¢é£ä»ããŸããRequirePermissionãRequireAuthorizationãAllowAnonymousãããŠRequireTenant: ãããžã§ã¯ãã®ãªãã·ã§ã³ã«åŸã£ãŠã»ãã¥ãªãã£ãé©çšããŸãã- æ§æã«å¿ããŠèªèšŒããªã·ãŒãŸãã¯å¿åããªã·ãŒã䜿çšããŠãã°ã«ãŒããŸãã¯endpoint ã¬ãã«ã§ã¬ãŒãå¶éãè¡ããŸãã
ãªã¯ãšã¹ããšã¬ã¹ãã³ã¹
ããã©ã«ãã§ã¯ãLino 㯠èšé² ãªã¯ãšã¹ããšã¬ã¹ãã³ã¹çšããããã¯ç°¡æœã§ãããã©ã«ãã§äžå€ã§ãããAPIãtyped clientsãããã³å€éšã³ã³ã·ã¥ãŒããŒéã®æç€ºçãªã³ã³ãã©ã¯ããšããŠé©åã«æ©èœããŸãã
- endpointçµç±ã§åä¿¡ãããªã¯ãšã¹ãã¯ã³ãã³ããŸãã¯ã¯ãšãªã«å€æãããŸãã
- ã³ãã³ããŸãã¯ã¯ãšãªã®çµæã¯å¿çã«å€æãããŸãã
- ãã¡ã€ã³ ãšã³ãã£ãã£ã¯ãã³ã³ãã©ã¯ã HTTP ãšããŠçŽæ¥å ¬éããªãã§ãã ããã
public record CreatePersonRequest(string Name, int Age); public record CreatePersonResponse(Guid Id, string Name, int Age);
æ°ãã API ã®äœæ
ãã¡ã€ã³ ã¢ãã«ãšãŠãŒã¹ã±ãŒã¹ã HTTP ã«ãã£ãŠå ¬éã§ããã»ã©ååã«æç¢ºã«ãªã£ãŠããå Žåã¯ãCLI ã«ãã£ãŠ API ãäœæããŸãã API ã¯ãMinimal APIsãã³ã³ãã©ã¯ããåä»ãã¬ã¹ãã³ã¹ãããã³ããã¥ã¡ã³ãã®ã¡ã¿ããŒã¿ãä»ããŠãã³ãã³ããšã¯ãšãªããã¬ãŒã³ããŒã·ã§ã³å±€ã«æ¥ç¶ããŸãã
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ãã¢ããããŒããããŠã³ããŒãããŸãã¯endpointã®ãªãã·ã§ã³ã - ã«ãŒã:ã«ãŒã ãã¿ãŒã³ããããª
/people/{id:guid}ã - ããããã£: å®éã« HTTP å¢çãè¶ããå¿ èŠããããªã¯ãšã¹ã ãã£ãŒã«ããšã¬ã¹ãã³ã¹ ãã£ãŒã«ãã
ãŠã£ã¶ãŒãã§èšå®ã§ããå 容
- åŸã: åäžã®çµæããªã¹ããããŒãžä»ããªã¹ããããã³ãªãã·ã§ã³/éžæã·ããªãªã
- 圹è·: ã³ãã³ã ã¿ã€ããšéžæããããããã£ãå«ããäœæããã³ããžãã¹ ã¢ã¯ã·ã§ã³ã
- 眮ã ãã㊠ããã: å®å šãŸãã¯éšåçãªæŽæ°ã
- æ¶å»: åé€ã³ãã³ãã«ããããããåé€ã
- ã¢ããããŒã: endpoint
IFormFileãããŠDisableAntiforgery()å¿ èŠã«å¿ããŠã - ããŠã³ããŒã:endpointãè¿ã
FileStreamHttpResult;èªèšŒããããããžã§ã¯ãã¯ãå®å šãªãã¡ã€ã« ã¢ã¯ã»ã¹ã®ããã®ããŒã¯ã³ endpointãçæã§ããŸãã - åæ: çæãããã¯ãšãªãšå¿çããšã«æå¹ãªãªãã·ã§ã³ãå ¬éããendpointã
æšå¥šãããŒ
- ãŠãŒã¹ã±ãŒã¹ã衚ããšã³ãã£ãã£ãã³ãã³ããã¯ãšãªãäœæãŸãã¯ç¢ºèªããŸãã
- èµ°ã
lino api newæ£ãããµãŒãã¹ãã¢ãžã¥ãŒã«ããšã³ãã£ãã£ãéžæããŸãã - ç®çã® HTTP åè©ã ãã§ãªãããŠãŒã¹ã±ãŒã¹ã«åºã¥ããŠæäœã®ã¿ã€ããéžæããŸãã
- 次ã®ãããªå¶çŽã䜿çšããŠãå®å®ããã«ãŒããå®çŸ©ããŸãã
{id:int}ãŸãã¯{id:guid}é©åãªå Žåã - HTTP å¢çãè¶ããå¿ èŠãããããããã£ã®ã¿ãéžæããŸãã
- èªå¯ãèš±å¯ãããã³ãèŠä»¶ãã¬ãŒãå¶éãããã³äºæãããã¹ããŒã¿ã¹ ã³ãŒããå®çŸ©ããŸãã
- ãã«ããå®è¡ããScalar/OpenAPI ãæ€æ»ããŠãã«ãŒããæŠèŠãããŒãžã§ã³ãã»ãã¥ãªãã£ãçæãããå¿çã確èªããŸãã
äŸ: CreatePersonal
API ãäœæããå Žå POST é»è©± CreatePersonããšã³ãã£ãã£ã«é¢é£ä»ããããŠãã PersonãCLI ã¯ãendpointãrequest/response contractsããããã³ã°æ¡åŒµæ©èœãOpenAPI ã¡ã¿ããŒã¿ãããã³å¯Ÿå¿ããã³ãã³ããšã®çµ±åãçæããŸãã
<ProjectName>/
âââ src/
âââ Services/
âââ <ServiceName>/
âââ Api/
âââ Endpoints/
âââ People/
âââ CreatePerson/
âââ CreatePersonEndpoint.cs
âââ CreatePersonExtensions.cs
âââ CreatePersonRequest.cs
âââ CreatePersonResponse.cs
å¥çŽãštyped clients
ãããžã§ã¯ãã« Web ã¢ã㪠Blazor ãããå ŽåãLino ã¯ãAPI ã®åä»ãæ¶è²»ã®ããã®ã¢ãŒãã£ãã¡ã¯ã (å ±æã³ã³ãã©ã¯ããã¯ã©ã€ã¢ã³ã ã€ã³ã¿ãŒãã§ã€ã¹ãããã³ HTTP å®è£ ) ãçæããŸããããã«ãããBlazor ã¯ãã·ã³ãã«ã§äžè²«æ§ããããå³å¯ã«åæå®ãããæ¹æ³ã§endpointã䜿çšã§ããããã«ãªããŸãã
<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åããŠãŒã¹ã±ãŒã¹ã§ã«ãŒãã®éè€ãç«¶åããendpointãé¿ããããã
Source Generator ã«ããendpointã®ç»é²
Lino ã¯ãSource Generatorsã䜿çšããŠå€§ããªãã¡ã€ã«ãæåã§ãããã³ã°ããããšãåé¿ããŸããendpointã 1 ã€ãã€ãªã¹ããã代ããã«ã Program.csããã°ã¯ã³ã³ãã€ã«äžã«çæãããŸãã
çæãããendpoint ã¯ã©ã¹ã®å®è£
IEndpoint ã® Tolitech.MinimalApis.Generators.Abstractionsãendpointã°ã«ãŒãã®åŒã³åºã MapEndpointsGenerated()ã«ãã£ãŠå¶äœãããŸããã Tolitech.MinimalApis.Generatorsãçæãããã³ãŒãã«ãã£ãŠæ°ããendpointãç»é²ãããŸãã
ãªããããéèŠãªã®ã
- æåé ç·ã®åæž: éçºè ã¯åendpointãæåã§ãããã³ã°ããããšãå¿ããå¿ èŠã¯ãããŸããã
- ã³ã³ãã€ã«æã®äžè²«æ§: endpointã¯åãæ§é ã«åŸããçæãããã³ãŒãã«ãã£ãŠæ€åºãããŸãã
- ããã¯ãªãŒã³ãªèµ·å:
Program.csãµãŒãã¹ãããã«ãŠã§ã¢ãæ¡åŒµã¡ãœãããæ§æããããã®ã»ããã¢ãããå§ä»»ããŸãã - AOTã®äºææ§: å®è¡æã®ãªãã¬ã¯ã·ã§ã³ãžã®äŸåãæžãããŸãã
- OpenAPI ã®äžè²«æ§: ã¿ã°ãæŠèŠãã¹ããŒã¿ã¹ ã³ãŒããããã³ããŒãžã§ã³ã¯endpointã§çæãããŸãã
- 建ç¯ã®èª¿æŽ: HTTP 㯠API ã«ããããªãŒã±ã¹ãã¬ãŒã·ã§ã³ã¯ MediatR ãçµç±ããã³ã³ãã©ã¯ãã¯ã¯ã©ã€ã¢ã³ããšå ±æã§ããŸãã
å®è¡æã®æµã
Program.csã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ãããµãŒãã¹ãŸãã¯ã¢ãžã¥ãŒã«ã®endpointããæ¡åŒµæ©èœãåŒã³åºããŸãã- æ¡åŒµæ©èœã¯ãAPI ããŒãžã§ã³ ã»ãããšendpoint ã°ã«ãŒããäœæããèªå¯/ã¬ãŒãå¶éãé©çšããŠåŒã³åºããŸãã
MapEndpointsGenerated()ã - çæãããããããŒã¯ã¡ãœãããåŒã³åºããŸã
MapEndpointåendpointã®ã - åendpointã¯ãã«ãŒããOpenAPI ã¡ã¿ããŒã¿ãæš©éãããã³ãèŠä»¶ãããã³ãã³ãã©ãŒããããããŸãã
- ãã³ãã©ãŒã¯å ¥å HTTP ãåãåãããããã³ãã³ã/ã¯ãšãªã«å€æããMediatR ã«éä¿¡ããŠãåæå®ãããçµæãè¿ããŸãã
ãšã©ãŒã®å®çŸ©
ãšã©ãŒå®çŸ©ã¯ãæ¢ç¥ã®ãã¡ã€ã³ããã³ã¢ããªã±ãŒã·ã§ã³ã®éå®³ãæšæºåããŸãããããã¯ãAPIããã³ãã©ãŒããã°ãããã³ããšã³ãããåendpointã§ã®è¿·èµ°ã¡ãã»ãŒãžãéè€æååããŸãã¯ã¢ãããã¯ãªæ±ºå®ã«äŸåããããšãªããäºæž¬å¯èœãªåé¡ãåŠçããã®ã«åœ¹ç«ã¡ãŸãã
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ããã¹ããå®å šã«åå¿ã§ããããã«ãå®å®ãããšã©ãŒ ã³ãŒããç¶æããŸãã
- endpointãçæã§ããã¹ããŒã¿ã¹ ã³ãŒãã OpenAPI ã«ææžåããŸãã
- ãµãŒããŒåŽã®ãã°ã䜿çšããŠã蚺æã®è©³çްãšå ¬éå¿çã®å®å šãªã¡ãã»ãŒãžãååŸããŸãã
