A NuGet package of extensions for the Microsoft.AspNetCore.OpenApi package.
Features include:
- Adding examples to OpenAPI operations and schemas.
- Customizing descriptions for:
- OpenAPI operation parameters and responses;
- OpenAPI schemas and their properties.
- Adding application URLs to the OpenAPI document.
- Adding OpenAPI schema documentation from XML comments.
- Adding an HTTP endpoint to get OpenAPI documents as YAML.
The library is also designed to be compatible with support for native AoT in ASP.NET Core 9.
A sample application using the library can be found here.
An overview of the library and how it works can be found on YouTube in this talk from .NET Conf 2024: 📺 Extending ASP.NET Core OpenAPI
To install the library from NuGet using the .NET SDK run the following command:
dotnet add package MartinCostello.OpenApi.Extensions
Below is an example code snippet showing how to use the features of the library:
using System.ComponentModel;
using System.Text.Json.Serialization;
using MartinCostello.OpenApi;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi((options) =>
{
// Configure ASP.NET Core support for OpenAPI documentation...
});
builder.Services.AddOpenApiExtensions((options) =>
{
// Always return the server URLs in the OpenAPI document
// Only enable this option in production if you are sure
// you wish to explicitly expose your server URLs.
options.AddServerUrls = true;
// Set a default URL to use for generation of the OpenAPI document using
// https://www.nuget.org/packages/Microsoft.Extensions.ApiDescription.Server.
options.DefaultServerUrl = "https://localhost:50001";
// Add examples for OpenAPI operations and components
options.AddExamples = true;
// Add JSON serialization context to use to serialize examples when enabled
options.SerializationContexts.Add(TodoJsonSerializerContext.Default);
// Add a custom example provider for ProblemDetails
options.AddExample<ProblemDetails, ProblemDetailsExampleProvider>();
// Configure XML comments for the schemas in the OpenAPI document
// from the assembly that the Program class is defined in.
options.AddXmlComments<Program>();
// Add a custom transformation for the descriptions in the OpenAPI document
options.DescriptionTransformations.Add((p) => p.ToUpper());
});
// Required if AddServerUrls=true
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
// Configure endpoint to get OpenAPI documents as JSON
app.MapOpenApi();
// Optionally also (or instead) configure endpoint to get OpenAPI documents as YAML
app.MapOpenApiYaml();
// The [Description] attribute can be used to add parameter descriptions
// The [OpenApiExample] attribute can be used to add simple string examples
// The ProducesOpenApiResponse() method can be used to customize the description for responses
app.MapGet("/todo", ([Description("The Todo item's ID"), OpenApiExample("42")] string id) =>
{
return new Todo()
{
Id = id,
Text = "Example",
IsComplete = false,
};
}).ProducesOpenApiResponse(StatusCodes.Status200OK, "The Todo item.");
app.MapPost("/todo", (Todo model) =>
{
var todo = new Todo()
{
Id = Guid.NewGuid().ToString(),
Text = model.Text,
IsComplete = false,
};
return Results.Created($"/todo/{todo.Id}", todo);
}).ProducesOpenApiResponse(StatusCodes.Status201Created, "The created Todo item.");
app.Run();
// Classes can implement IExampleProvider<Todo> and decorate
// themselves with the [OpenApiExample<T>] attribute to use
// the example for all usage of the type in the OpenAPI document.
// Examples can also be added as attributes to parameters of operations,
// endpoint methods themselves, or as endpoint metadata.
[OpenApiExample<Todo>]
public class Todo : IExampleProvider<Todo>
{
public string Id { get; set; }
public string Text { get; set; }
public bool IsComplete { get; set; }
public static Todo GenerateExample() =>
new()
{
Id = "42",
Text = "Buy milk",
IsComplete = false,
};
}
// Custom IExampleProvider<T> implementations can be used to add more specific
// examples for types in the OpenAPI document, or for types that are not owned
// by the application itself (e.g. ASP.NET Core's ProblemDetails class).
public class ProblemDetailsExampleProvider : IExampleProvider<ProblemDetails>
{
public static ProblemDetails GenerateExample()
{
return new()
{
Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1",
Title = "Bad Request",
Status = StatusCodes.Status400BadRequest,
Detail = "The specified value is invalid.",
};
}
}
// JSON source generation context to use to generate examples for JSON
// payloads that matches the runtime behaviour of the application itself
// (for example whether to use camelCase or PascalCase etc.)
[JsonSerializable(typeof(Todo))]
[JsonSerializable(typeof(ProblemDetails))]
[JsonSourceGenerationOptions(
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
WriteIndented = true)]
public partial class TodoJsonSerializerContext : JsonSerializerContext;
Compiling the application yourself requires Git and the .NET SDK to be installed.
To build and test the application locally from a terminal/command-line, run the following set of commands:
git clone https://github.com/martincostello/openapi-extensions.git
cd openapi-extensions
./build.ps1
Any feedback or issues can be added to the issues for this project in GitHub.
The repository is hosted in GitHub: https://github.com/martincostello/openapi-extensions.git
This project is licensed under the Apache 2.0 license.