apigenie-generatorAsyncAPI clientsclient csharp (AsyncAPI)
client csharp (AsyncAPI)
Generate a C# Kafka client library for the Kafka channels of an AsyncAPI document.
Usage
apigenie-generator client csharp [...OPTIONS] INPUT_FILE
Description
apigenie-generator client csharp generates from OpenAPI documents (see
apigenie-generator client csharp) and from AsyncAPI 3.x
documents. It tells them apart by their openapi or asyncapi field. Documents that reference
other files are bundled first.
From an AsyncAPI document it generates a .NET 8 class library (Microsoft.NET.Sdk) on the Kafka
client Confluent.Kafka (Apache-2.0, pinned
at 2.15.1). It also references Microsoft.Extensions.Hosting.Abstractions and
Microsoft.Extensions.Options.ConfigurationExtensions.
By default the client implements the counterpart of the application the document describes: it
sends the messages of the application’s receive operations, and receives the messages of its
send operations. Set the perspective option to application to generate the application’s
side instead. The two sides talk to each other, and to the application of
apigenie-generator server aspnet (AsyncAPI).
The generator writes the Kafka channels:
- the channels of servers with the
kafkaorkafka-secureprotocol; - in documents without servers, the channels with a Kafka binding.
Channels of other protocols are skipped and reported as info.
// the application's side of the Carpet Express Event Platform
builder.Services.AddCarpetExpressKafkaClient(builder.Configuration);
public sealed class Shipping(CarpetExpressKafkaClient kafka)
{
public async Task DeliveredAsync(ShipmentDelivered message, CancellationToken cancellationToken)
{
await kafka.ShipmentEvents.SendShipmentDeliveredAsync(message, cancellationToken);
}
public async Task<Uri?> LabelAsync(RenderLabel request, CancellationToken cancellationToken)
{
// sends the request with a new correlation id and waits for its reply
var reply = await kafka.LabelRenderRequests.RequestRenderLabelAsync(request, TimeSpan.FromSeconds(10), cancellationToken);
return reply is LabelRendered rendered ? rendered.Payload.Url : null;
}
}
The project’s root namespace (and assembly name) is root_namespace, else --package-name, else
the document’s title in PascalCase followed by .Client. The class names start with the
namespace’s stem: its last segment, or the segment before a last Client, Clients or Sdk. For
example, CarpetExpress.Client gives CarpetExpressKafkaClient.
| File | Contents |
|---|---|
Models/*.cs, Serialization/*.cs, Messages/*.cs |
the payload types, the JSON context and the message records, as apigenie-generator server aspnet (AsyncAPI) writes them |
Kafka/<Name>KafkaClient.cs |
the client: a producer per channel it sends to |
Kafka/<Channel>Producer.cs |
the Send…Async and Request…Async methods of a channel |
Kafka/*Handler.cs, Kafka/*Consumer.cs |
the handler interfaces and consumers of the received operations |
Kafka/<Name>KafkaClientOptions.cs |
the options, with the topics and ids |
Kafka/<Name>KafkaClientServiceCollectionExtensions.cs, Kafka/<Name>KafkaClientBuilder.cs |
Add<Name>KafkaClient and the registration of handlers |
Infrastructure/*.cs |
the Kafka runtime (producer, consumer service, reply consumer, headers) and the validation of messages |
<RootNamespace>.csproj, README.md |
the project |
-
Sent operations. The client has a producer per channel, e.g.
client.ShipmentEvents. A producer’sSend<Message>Asyncvalidates a message and completes once the brokers have it. It writes the constant headers (e.g.ce_type), the key and the topic from the bindings. -
Request/reply. A request/reply operation gets
Request<Message>Async(message, cancellationToken)and an overload with a timeout.- It sends the request with its correlation id, or with a new Guid when the request has none.
- It returns the reply: the reply message, or an interface of the replies
(
IRequestLabelRenderReply) when there are several. - It throws
TimeoutExceptionwhen no reply comes within the timeout (by defaultReplyTimeout), andOperationCanceledExceptionwhen the token is cancelled.
One consumer per client reads the replies of every request. It has no consumer group, and starts with the first request reading from a minute before, so no reply is missed.
-
Received operations. They have handler interfaces and consumers, as in apigenie-generator server aspnet (AsyncAPI):
- the dispatch by a payload property or a header, with
OnUnknownAsyncfor other records; - validation;
- commits once the handler returns, and retries after
RetryDelaywhen it throws; - replies sent with the request’s correlation id.
Register a handler with the builder: its consumer runs as a hosted service of the host.
- the dispatch by a payload property or a header, with
// the counterpart's side: consume the shipment events and answer label requests
builder.Services.AddCarpetExpressKafkaClient(builder.Configuration)
.AddPublishShipmentEventsHandler<ShipmentEventsHandler>()
.AddRequestLabelRenderHandler<LabelRenderer>();
Add<Name>KafkaClient(configuration, configure) does the following:
- binds the options to the
AsyncApi:Kafkasection ofconfigurationwhen it is given, then appliesconfigure; - registers the client and its producers as singletons;
- returns the builder.
Without dependency injection, new CarpetExpressKafkaClient(options) sends and requests; dispose
it when done.
Settings
The options are those of apigenie-generator server aspnet (AsyncAPI):
BootstrapServers, ClientId, ReplyTimeout, RetryDelay, Topics, Operations (the group
and client ids of received operations), Consumer and Producer. A client that sends requests
also has ReplyClientId, the client id of its reply consumer. It defaults to the client id of the
first request/reply operation’s Kafka binding. Without a value in the binding, the default is
<namespace stem in kebab case>-<operation>.
Not supported, and reported as warnings:
- Avro payloads, and payloads of other non-JSON schema formats;
- reply addresses given by runtime expressions;
- Kafka topics with parameters.
Security (SASL/SCRAM, mTLS) is not configured: set the librdkafka properties in Consumer and
Producer.
Extensions
| Extension | Effect |
|---|---|
x-apigenie.codegen.disabled |
true on a channel or an operation leaves it out (with the operations of a channel left 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 |
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.OrderStatus
update:
x-enum-varnames: [Created, Paid, Shipped]
- target: $.operations.publishAudit
update:
x-apigenie:
codegen:
disabled: true
apigenie-generator client csharp asyncapi.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. The overlays
apply to the AsyncAPI document bundled with the files it references.
–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.Events.Client. Defaults to the title of the API
in PascalCase, followed by .Client.
–package-version
Version of the project. Defaults to the version of the API when it is a .NET version, else 1.0.0.
-p, –property
Applies to OpenAPI documents only. Using it with an AsyncAPI document is an error.
Configuration
The options are read from the asyncapi section of the configuration of apigenie-generator client csharp.
Its other keys configure the generation from OpenAPI documents.
version: '1.0'
commands:
generate:
client_csharp:
asyncapi:
root_namespace: Acme.Events.Client
validation: true
perspective: counterpart
| Option | Description |
|---|---|
root_namespace |
Root namespace and assembly name of the project (default: --package-name, or the title followed by .Client) |
validation |
true (default): validate messages by their DataAnnotations before sending and after receiving them |
perspective |
counterpart (default): the counterpart of the described application; application: the application itself |