Skip to content

Latest commit

 

History

900 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

OpenAPI Extensions for ASP.NET Core

NuGet NuGet Downloads

Build status codecov OpenSSF Scorecard

Introduction

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.

There is also a sample application using the library.

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

Installation

To install the library from NuGet using the .NET SDK run the following command:

dotnet add package MartinCostello.OpenApi.Extensions

Usage

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;

Building and Testing

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

Feedback

Any feedback or issues can be added to the issues for this project in GitHub.

Repository

The repository is hosted in GitHub: https://github.com/martincostello/openapi-extensions.git

License

This project is licensed under the Apache 2.0 license.

About

Extensions for Microsoft.AspNetCore.OpenApi

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

103 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages