Skip to content

Microsoft.AspNetCore.OpenApi

The Cratis.Arc.OpenApi package provides deep integration with Microsoft.AspNetCore.OpenApi (.NET 10+), adding schema and operation transformers for Arc conventions. Review the enum and model-bound response limitations below before treating generated schemas as a wire-contract guarantee. This is the ASP.NET host integration, not Core’s built-in lightweight OpenAPI.

TopicDescription
ConceptsHow concept types are mapped to their underlying primitive types in the API schema.
CommandsHow command responses are wrapped with CommandResult in the API documentation.
QueriesHow query responses are wrapped with QueryResult, including pagination parameters.
EnumsEnum schemas follow the effective JSON converter’s numeric or string wire values.
FromRequest AttributeHow complex model binding with [FromRequest] is reflected in the API schema.
Model-Bound OperationsHow minimal API command and query endpoints appear in the API documentation.

Add the Cratis.Arc.OpenApi NuGet package to your project and call AddConcepts() inside your AddOpenApi configuration:

These are configuration fragments for an existing ASP.NET Core Arc host. Import Cratis.Arc.OpenApi and Microsoft.Extensions.DependencyInjection, then register before builder.Build():

builder.Services.AddOpenApi(options => options.AddConcepts());

After building the app, map the document using ASP.NET’s app.MapOpenApi() (default /openapi/v1.json). Keep app.UseCratisArc() and the host’s normal startup too. Map only in intended environments or apply appropriate endpoint access controls; API documentation is not automatically private.

The AddConcepts() method registers the schema and operation transformers. By default, concept values and collections use primitive schemas, and recursive values in dictionaries keyed by concepts use component references. A custom concept converter can change the wire shape; OpenAPI leaves its schema unspecified unless you provide a matching schema transformer. The other transformers describe effective converters: date, time, URI and type strings, GeoJSON objects, and polymorphic base properties are handled when an application explicitly configures the corresponding Arc converter on its HTTP JSON options. AddCratisArc() does not install those non-concept converters on plain minimal APIs. Without them, ASP.NET’s defaults determine the wire format and schema.

With Fundamentals’ derived-type converter explicitly enabled, the base schema lists declared interface properties by camel-cased CLR name. A plain minimal API Results.Ok<ISampleBase>(derived) response uses the runtime concrete type: it includes derived-only properties but no _derivedTypeId discriminator. The base schema does not list the derived-only properties. Serialization explicitly through the declared interface with Fundamentals’ converter can include _derivedTypeId; verify the actual endpoint contract before generating clients. [JsonPropertyName] and [JsonIgnore] on a base interface do not affect this converter’s concrete property writes. Avoid indexers on derived types: the converter attempts to read them without arguments and cannot serialize them.

The Cratis.Arc.OpenApi package targets .NET 10 and later. The transformer API (IOpenApiSchemaTransformer, IOpenApiOperationTransformer) and the underlying Microsoft.OpenApi 2.x schema types are only available from .NET 10 onwards.

Arc also ships a separate Cratis.Arc.Swagger package for Swashbuckle-based Swagger UI. Both packages cover the same set of Arc features, but use different APIs:

Cratis.Arc.SwaggerCratis.Arc.OpenApi
FrameworkSwashbuckle (ISchemaFilter, IOperationFilter)Microsoft.AspNetCore.OpenApi (IOpenApiSchemaTransformer, IOpenApiOperationTransformer)
HostASP.NET CoreASP.NET Core
Registrationservices.AddSwaggerGen(o => o.AddConcepts())services.AddOpenApi(o => o.AddConcepts())

Both are fully independent; choose the one that matches your toolchain.