apigenie-generatorOpenAPI serversserver aspnet

server aspnet

Generate an ASP.NET Core server in C#, built on Minimal APIs.

From an AsyncAPI document, the command generates an ASP.NET Core Kafka application instead; see apigenie-generator server aspnet (AsyncAPI).

Usage

apigenie-generator server aspnet [...OPTIONS] INPUT_FILE

Description

The input must be an OpenAPI 3.0, 3.1 or 3.2 document. Convert Swagger 2.0 documents with apigenie convert, and bundle documents referencing other files with apigenie bundle.

The generated project targets .NET 8 (or 9 and 10, see target_framework) and uses only the shared framework, without NuGet packages:

PetStore.csproj
Program.cs                  the host, written only when missing
README.md
ApiRegistration.cs          MapPetStoreApi(): maps the endpoints of all operations
Apis/IPetsApi.cs            one interface per group of operations
Apis/PetsApi.cs             its implementation, written only when missing
Endpoints/PetsEndpoints.cs  routes, parameter binding, validation and metadata
Models/Pet.cs               records and enums of the schemas
Infrastructure/*.cs         helpers used by the generated code

Operations are grouped by their first tag (or by the first segment of their paths). Each group gets an interface whose methods return the responses of the operation as a union of typed results, so the compiler accepts only declared responses:

public interface IPetsApi
{
    /// <summary>Find a pet</summary>
    /// <remarks>GET /pets/{petId}</remarks>
    Task<Results<Ok<Pet>, NotFound, GoneResult<Error>>> GetPet(long petId, CancellationToken cancellationToken);
}

Implementations return TypedResults.Ok(pet), TypedResults.NotFound() and the like. Statuses without a TypedResults method (403, 410, 429, 500, …) have result types of their own, created with ApiResults.Gone(error). All results describe their responses in the endpoint metadata, so OpenAPI documents produced by ASP.NET Core match the input.

The endpoints bind parameters from the path, the query, headers and cookies, with the styles of the document (exploded or delimited arrays), JSON, text, binary, form and multipart bodies, and resolve the implementation from the services of the request:

var app = builder.Build();
app.MapPetStoreApi();

Models are records with required properties, System.Text.Json attributes and DataAnnotations attributes for the constraints of the schemas (minimum, maxLength, pattern, format: email, maxItems, …). An endpoint filter checks them, and the values of enums, before the implementation is called, and answers invalid requests with 400 validation problem details.

  • oneOf and anyOf with a discriminator become abstract records with [JsonPolymorphic] attributes, and their variants derive from them. On .NET 8, System.Text.Json reads the discriminator only as the first property of an object.
  • allOf referencing a schema with a discriminator becomes inheritance; other allOf schemas are merged into one record.
  • String enums become C# enums whose converters read and write the values of the document, e.g. in-progress. Integer enums keep their values. The x-enum-varnames extension names members.
  • Inline object and enum schemas get types named after their location, e.g. PetOwner for the owner property of Pet. Identical inline schemas share a type.
  • Schemas whose names would clash with types of .NET (Task, File, Environment, …) get a Model suffix.

Operations with security requirements call RequireAuthorization(); configure the authentication schemes in Program.cs, which lists the schemes of the document.

Not supported: oneOf and anyOf without a discriminator whose members have different types (typed object; members of one type, e.g. strings of different formats, give that type), not, if/then/else, separate request and response variants of models with readOnly and writeOnly properties (such properties are optional), prefixItems, patternProperties, multipleOf, dependentRequired, dependentSchemas, unevaluatedProperties, object query parameters (deepObject, left out with a warning), parameters described by content (left out with a warning), the deepObject encoding and the constraints of form fields, response headers, more than one media type per response (JSON wins: no text/event-stream, JSON Lines or binary alternatives), callbacks and webhooks, operation and path servers (every route is below the path of the first server), and OAuth 2.0 scopes (operations only call RequireAuthorization() with the default policy).

Extensions

Extension Effect
x-apigenie.codegen.controller-name on an operation or its path item: the group (API interface) of the operation, whatever grouping says
x-apigenie.codegen.action-name name of the method of an operation, when action_naming lists extension
x-apigenie.codegen.disabled true on an operation or its path item leaves the operation out, unless skip_disabled is false
x-internal true on an operation leaves it out
x-enum-varnames, x-enum-names names of the members of an enum, in PascalCase
x-enum-descriptions, x-enumDescriptions documentation comments of the members of an enum
x-defaultMapping defaultMapping of a discriminator in OpenAPI 3.0 and 3.1 documents: the schema of the values whose discriminator value isn’t mapped

The extensions can live in an overlay for this target instead of in the document, e.g. aspnet.overlay.yaml:

overlay: 1.0.0
info:
  title: ASP.NET names
  version: 1.0.0
actions:
  - target: $.components.schemas.PetStatus
    update:
      x-enum-varnames: [Available, OnHold, Sold]
  - target: $.paths['/pets']
    update:
      x-apigenie:
        codegen:
          controller-name: Animals
apigenie-generator server aspnet openapi.yaml --overlay aspnet.overlay.yaml -o out

Options

-c, –config

Path to the configuration file to use. See the “Configuration” section for more information.

–overlay OVERLAY

Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the extensions of the “Extensions” section. Can be repeated: the overlays apply in order, after those listed under commands.generate.server_aspnet.overlay in the configuration file (with paths relative to it). Warnings and errors about a value an overlay set point to the overlay.

–strict

Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated) instead of a warning (OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.).

-o, –output

Directory where the project is generated.

–package-name

Root namespace of the generated code, e.g. Acme.PetStore; also the name of the project. Defaults to the title of the API.

–package-version

Version of the project. Defaults to the version of the API when it’s a valid .NET version, or 1.0.0.

-p, –property NAME=VALUE

Sets an option (see below), e.g. -p layout=sources; can be repeated. Options given on the command line take precedence over the configuration file. OpenAPI documents only: using it with an AsyncAPI document is an error.

Configuration

The options are read from commands.generate.server_aspnet. Its asyncapi section configures the generation from AsyncAPI documents (see apigenie-generator server aspnet (AsyncAPI)).

version: '1.0'
commands:
  generate:
    server_aspnet:
      namespace: Acme.PetStore
      target_framework: net10.0
      grouping: url
Option Values Description
layout project, sources project (default): a complete project (.csproj, Program.cs, README.md); sources: only the generated sources, for an existing project
namespace namespace Root namespace of the generated code (also --package-name); derived from the API title by default
target_framework net8.0, net9.0, net10.0 Target framework of the project (default: net8.0)
grouping tag, url Grouping of operations into API interfaces: by their first tag (default), or by the first segment of their paths
action_naming id, extension, url Sources of method names, in order of preference (default: id, url)
validation filter, none filter (default): an endpoint filter validates parameters and bodies against their DataAnnotations; none: attributes only
authorization require, none require (default): operations with security requirements call RequireAuthorization(); none: no authorization metadata
base_path servers, none servers (default): routes are prefixed with the path of the first server URL; none: no prefix
program true, false Generate Program.cs and stub implementations of the API interfaces (written only when missing; default: true)
skip_deprecated true, false Don’t generate deprecated operations (default: false)
skip_disabled true, false Don’t generate operations disabled with the x-apigenie extension (default: true)
model_suffix text Suffix of model names, e.g. Dto
version version Version of the project (also --package-version); defaults to the version of the API

Unknown options are errors.