apigenie-generatorOpenAPI clientsclient csharp
client csharp
Generate a C# client of an OpenAPI document, built on HttpClient and System.Text.Json, for
.NET 8 (or 9 and 10).
From an AsyncAPI document, the command generates a C# Kafka client library instead; see apigenie-generator client csharp (AsyncAPI).
Usage
apigenie-generator client csharp [...OPTIONS] INPUT_FILE
Description
The input must be an OpenAPI 3.0, 3.1 or 3.2 document. The output is a class library: a .csproj
targeting net8.0 with nullable reference types, which references only Microsoft.Extensions.Http
(for the registration with dependency injection).
services.AddPetStoreClient(options =>
{
options.BaseUrl = new Uri("https://api.example.com/v1");
options.ApiKey = ApiCredential.Static(configuration["PetStore:ApiKey"]!);
});
// inject PetStoreClient, or the client of a group, e.g. IPetsClient
var pets = await client.Pets.ListPetsAsync(limit: 10, cancellationToken: token);
try
{
var pet = await client.Pets.GetPetAsync(42);
}
catch (ApiException error) when (error.StatusCode == 404)
{
Console.WriteLine(error.Problem?.Detail);
}
Without dependency injection, PetStoreClient.CreateHttpClient(options) makes an HttpClient that
sends the credentials: new PetStoreClient(PetStoreClient.CreateHttpClient(options), options).
The generated code has:
- Clients. One interface and one client per group of operations (
IPetsClient,PetsClient), grouped by their first tag (seegrouping), andPetStoreClientwith a property per group. The clients take theHttpClientin their constructor, soIHttpClientFactorymanages them;AddPetStoreClient()registers them as typed clients, with the options and the handlers sending the credentials. Operations markedx-internalare left out. - Methods. An
asyncmethod per operation, named after its operation ID (ListPetsAsync, seeaction_naming): path parameters, the other required parameters and the body first, optional parameters (nullleaves them out) and aCancellationTokenlast. Parameters are sent in their style (form, spaceDelimited, pipeDelimited, deepObject, simple, label, matrix), objects included; parameters described bycontentare sent as JSON. Deprecated operations are[Obsolete]. - Bodies. JSON (with the media type of the document, e.g.
application/merge-patch+json), text, binary (Stream), JSON Lines uploads (IAsyncEnumerable<T>), and forms and multipart bodies as*Formclasses, whose files areFileParts (format: binaryorcontentMediaType) sent with the content type of theirencoding. - Responses. The method returns the body of the success response (
Task<Pet>), nothing (Task), or, when statuses have different bodies, a*Resultwith the status, the headers and a property per status. Responses with a status of 400 or more throw anApiExceptionwith the status, the headers, the body as text and its RFC 9457 problem details (Problem).text/event-streamresponses areIAsyncEnumerable<ServerSentEvent<T>>, typed by thecontentSchemaof the events’ data (OpenAPI 3.2itemSchema, orx-itemSchema), JSON Lines responsesIAsyncEnumerable<T>, both read as they arrive; binary responses areBinaryResponses to dispose. Each other media type of a body or a response is a method of its own, named after it:UpdatePetJsonPatchAsync,GetLabelPdfAsync,GetEventsEventStreamAsync. - Servers. Requests go to
BaseUrl, else to the base address of theHttpClient, else to the first server of the operation, of its path or of the API, withServerVariablesfor their variables. - Security. A credential per security scheme in the options (
ApiCredential.Static,ApiCredential.FromProviderfor tokens that change,ApiCredential.Basic). A request carries the credentials of the first alternative of its operation’s security requirements whose credentials are set; theAuthorizationHandler(HTTP schemes such as bearer and basic, OAuth 2.0, OpenID Connect) andApiKeyHandler(headers, query parameters, cookies) delegating handlers add them. - Models. Records and enums, as
apigenie-generator server aspnetwrites them:required/initproperties, DataAnnotations for constraints (exclusive bounds of OpenAPI 3.0 and 3.1 alike), nullable types fornullable,nulltypes andoneOfwithnull.allOfis merged into one record, or is inheritance ([JsonPolymorphic]/[JsonDerivedType]) when the base has a discriminator.oneOfandanyOfwith a discriminator are abstract records whose variants are told apart by the discriminator value (explicit mapping, or theconstof the discriminator property, or the schema name), read and written by generated converters wherever the discriminator is in the object; values with an unknown discriminator are read as the default mapping (defaultMapping, orx-defaultMapping). Unions whose members have one C# type (e.g. strings of different formats) have that type. - JSON. A
System.Text.Jsonsource-generatedJsonSerializerContext(PetStoreJsonContext) with every model and body type, so the clients read and write JSON without reflection. Use it to read error bodies:JsonSerializer.Deserialize(error.Content!, PetStoreJsonContext.Default.Error).
The project also has README.md, Infrastructure/ (the runtime of the clients) and
Serialization/ (the JSON context and converters). The code builds with -warnaserror and the
.NET analyzers.
Not supported: callbacks and webhooks, OAuth 2.0 flows (the caller supplies access tokens),
mutual TLS (configure the client certificate on the HTTP handler), XML bodies (sent and read as
text), prefixItems, patternProperties, if/then/else, dependentRequired,
dependentSchemas, unevaluatedProperties, multipleOf, retries (add a
resilience handler with configureHttpClient) and pagination.
Extensions
| Extension | Effect |
|---|---|
x-apigenie.codegen.controller-name |
on an operation or its path item: the group (client) 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 |
x-itemSchema |
itemSchema of a media type in OpenAPI 3.0 and 3.1 documents: the type of the items of a streamed response |
The extensions can live in an overlay for this target instead of in the document, e.g.
csharp.overlay.yaml:
overlay: 1.0.0
info:
title: C# 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 client csharp openapi.yaml --overlay csharp.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.client_csharp.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.Client; also the name of the project.
The API-wide types are named after its last segment (or the one before when it is Client,
Clients or Sdk): PetStoreClient, PetStoreClientOptions. Defaults to the title of the API
followed by .Client.
–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.client_csharp. Its asyncapi section configures
the generation from AsyncAPI documents (see
apigenie-generator client csharp (AsyncAPI)).
version: '1.0'
commands:
generate:
client_csharp:
namespace: Acme.PetStore.Client
target_framework: net9.0
grouping: tag
dependency_injection: true
| Option | Values | Description |
|---|---|---|
layout |
project, sources |
project (default): a class library (.csproj, README.md and the sources); 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, e.g. PetStore.Client |
target_framework |
net8.0, net9.0, net10.0 |
Target framework of the project (default: net8.0) |
grouping |
tag, url |
Grouping of operations into clients: 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) |
dependency_injection |
true, false |
Generate the registration of the clients with IServiceCollection and IHttpClientFactory (default: true; it references Microsoft.Extensions.Http) |
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.