Repository navigation
Description
Summary
Create a shared .NET library named TransactionProcessing.ApiDefaults to provide a consistent configuration for ASP.NET Core Minimal APIs.
The initial version of the library should standardise:
- API versioning using
Asp.Versioning - URL-based API versions (
/api/v1/...,/api/v2/...) - OpenAPI document generation
- A separate OpenAPI document for each supported API version
- Scalar as the API documentation UI
The intention is to allow individual APIs to enable the standard configuration with minimal setup while keeping endpoint definitions and application-specific behaviour within the individual API projects.
Target Framework
Target .NET 10.
Required Packages
Use the current compatible versions of:
Asp.Versioning.HttpAsp.Versioning.Mvc.ApiExplorerMicrosoft.AspNetCore.OpenApiScalar.AspNetCore
Avoid introducing Swashbuckle unless it is required for functionality that cannot be provided by the standard ASP.NET Core OpenAPI implementation.
API Versioning
Configure API versioning centrally using Asp.Versioning.
The standard configuration should:
- Use URL segment versioning.
- Support URLs in the form:
/api/v1/transactions
/api/v2/transactions
- Use
1.0as the initial/default API version. - Require the version to be explicitly specified in the URL.
- Report supported and deprecated API versions in HTTP responses.
- Configure the API Explorer for versioned endpoints.
- Use version group names such as
v1,v2, etc. - Substitute the API version into generated URLs.
Example endpoint configuration:
var api = app.NewVersionedApi("Transactions");
var transactions = api
.MapGroup("/api/v{version:apiVersion}/transactions")
.HasApiVersion(1.0)
.HasApiVersion(2.0);Endpoints should be able to support one or multiple versions:
transactions
.MapGet("/{id:guid}", GetTransaction)
.MapToApiVersion(1.0)
.MapToApiVersion(2.0);Version-specific implementations must also be supported:
transactions
.MapPost("/", CreateTransactionV1)
.MapToApiVersion(1.0);
transactions
.MapPost("/", CreateTransactionV2)
.MapToApiVersion(2.0);OpenAPI
Use the standard ASP.NET Core OpenAPI implementation provided by Microsoft.AspNetCore.OpenApi.
Generate a separate OpenAPI document for each discovered API version.
For example:
/openapi/v1.json
/openapi/v2.json
The OpenAPI documents should be generated from the API versions registered through Asp.Versioning.
Adding a new API version to an application's endpoints should not require manually registering another OpenAPI document.
For example, adding V3 should automatically result in:
/openapi/v3.json
Each document should contain only the endpoints applicable to that API version.
An endpoint mapped to both V1 and V2 should therefore appear in both documents, while a V2-only endpoint should only appear in the V2 document.
Scalar
Use Scalar.AspNetCore to provide an interactive API documentation UI.
Expose the documentation at a consistent route, preferably:
/scalar
Scalar should expose all discovered API versions and allow the user to switch between their OpenAPI definitions.
For example:
Transaction API
API Definition:
V1
V2
These should resolve to:
/openapi/v1.json
/openapi/v2.json
The Scalar configuration should automatically include newly discovered API versions.
Configuration
Provide an options object allowing individual APIs to supply basic documentation metadata.
For example:
builder.Services.AddApiDefaults(options =>
{
options.Title = "Transaction API";
options.Description = "Transaction processing services";
});Initial options should include:
public sealed class ApiDefaultsOptions
{
public string Title { get; set; } = "API";
public string? Description { get; set; }
}Do not add application-specific configuration to this options object.
Public API
The desired setup within an ASP.NET Core application should be approximately:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddApiDefaults(options =>
{
options.Title = "Transaction API";
options.Description = "Transaction processing services";
});
var app = builder.Build();
app.UseApiDefaults();
app.MapTransactionEndpoints();
app.Run();The consuming application should not need to configure Asp.Versioning, OpenAPI or Scalar directly.
Suggested Project Structure
TransactionProcessing.ApiDefaults
│
├── ApiDefaultsOptions.cs
├── ApiDefaultsExtensions.cs
│
├── Versioning
│ ├── ApiVersions.cs
│ └── ApiVersioningExtensions.cs
│
└── OpenApi
├── OpenApiExtensions.cs
├── OpenApiDocumentConfiguration.cs
└── ScalarExtensions.cs
The exact internal structure can change if a cleaner implementation is identified.
API Version Constants
Provide standard version constants to avoid repeatedly constructing ApiVersion instances.
For example:
public static class ApiVersions
{
public static readonly ApiVersion V1 = new(1, 0);
public static readonly ApiVersion V2 = new(2, 0);
}Consumers should be able to use these when defining endpoints:
.HasApiVersion(ApiVersions.V1)
.MapToApiVersion(ApiVersions.V1)The design should not require this class to be modified merely for OpenAPI to discover a new version.
Separation of Responsibilities
The shared library should contain infrastructure and conventions only.
It should not contain:
- Application endpoints
- Request/response DTOs
- Business logic
- Application-specific authentication rules
- Transaction-specific behaviour
Endpoint ownership remains with the consuming application.
Testing
Add automated tests covering the shared configuration.
At minimum verify:
- V1 endpoints are accessible through
/api/v1/.... - V2 endpoints are accessible through
/api/v2/.... - An unsupported API version is rejected appropriately.
- An endpoint mapped to V1 and V2 works through both versions.
- A V1-only endpoint is unavailable through V2.
- A V2-only endpoint is unavailable through V1.
/openapi/v1.jsonis generated./openapi/v2.jsonis generated.- The V1 OpenAPI document contains only V1-compatible endpoints.
- The V2 OpenAPI document contains only V2-compatible endpoints.
- Scalar is available and references the generated versioned OpenAPI documents.
Prefer integration tests using a small test Minimal API rather than testing implementation details of the extension methods.
Acceptance Criteria
The work is complete when:
TransactionProcessing.ApiDefaultstargets .NET 10.- A consuming Minimal API can enable the functionality using
AddApiDefaults(...)andUseApiDefaults(). - URL segment API versioning is configured consistently.
- API versions are discoverable without duplicate OpenAPI configuration.
- A separate OpenAPI document is generated for each API version.
- OpenAPI documents contain only endpoints applicable to their version.
- Scalar displays the available API definitions.
- Adding another API version does not require changes to the consuming application's OpenAPI/Scalar configuration.
- Common API configuration is contained within the shared library.
- Automated integration tests demonstrate the expected behaviour.
- No application-specific business logic is introduced into the shared library.
Out of Scope
For the initial implementation, do not include:
- Authentication/authorisation configuration
- JWT/OpenAPI security configuration
- Health checks
- Problem Details
- Exception handling
- Correlation IDs
- Logging configuration
- Telemetry/observability
- Rate limiting
These can be introduced separately once there is a demonstrated need for them across multiple APIs.
Activity