APIWeaver.OpenApi
is a lightweight .NET 9 library that extends the OpenAPI document generated by .NET's built-in OpenAPI document generator. It’s compatible with native AOT and offers extension methods and transformers for flexible customization.
To get started with APIWeaver, install the APIWeaver.OpenApi
NuGet package.
dotnet add package APIWeaver.OpenApi
Add the following using directive to your Program.cs
file.
using APIWeaver;
The package provides straightforward methods to add security schemes to your OpenAPI documents. The snippet below shows how to set up a security scheme:
builder.Services.AddOpenApi(options =>
{
// Adds a security scheme to the OpenAPI document and updates operations
options.AddSecurityScheme("Bearer", scheme =>
{
scheme.In = ParameterLocation.Header;
scheme.Type = SecuritySchemeType.OAuth2;
scheme.Flows = new OpenApiOAuthFlows
{
ClientCredentials = new OpenApiOAuthFlow
{
TokenUrl = new Uri("https://localhost:5001/oauth2/token")
}
};
});
// Adds 401 and 403 responses based on endpoint requirements
options.AddAuthResponse();
});
The AddSecurityScheme
method adds a security scheme to the OpenAPI document and applies it to relevant operations. AddAuthResponse
automatically adds 401 (Unauthorized) and 403 (Forbidden) responses to operations that require specific roles or policies.
Add pre-configured examples for specific types in your OpenAPI document:
builder.Services.AddApiWeaver(options =>
{
options.AddExample(new Book
{
BookId = Guid.NewGuid(),
Title = "APIWeaver",
Description = "A book about APIWeaver",
BookType = BookType.Documentation,
Pages = 69
});
});
You can also implement the IExampleProvider
interface to generate examples:
internal sealed class BookExampleProvider: IExampleProvider<Book>
{
public static Book GetExample() => new()
{
BookId = Guid.NewGuid(),
Title = "APIWeaver",
Description = "A book about APIWeaver",
BookType = BookType.Documentation,
Pages = 69
};
}
builder.Services.AddApiWeaver(options =>
{
options.AddExample<Book, BookExampleProvider>();
});
Note
Multiple examples of the same type cannot be added
Add examples for specific parameters using the [Example]
attribute:
books.MapGet("/{bookId:guid}", ([Example("115f3511-812d-4062-a212-5a197d23acdc")] Guid bookId) =>
{
// Get the book by ID
});
books.MapGet("/", ([Example(69)] [FromQuery] int pages) =>
{
// Get books by pages
});
Note
The [Example]
attribute only works for primitive types.
You can easily add and customize response descriptions for your OpenAPI operations
builder.Services.AddOpenApi(options =>
{
// Registers transformers to enable response descriptions
options.AddResponseDescriptions();
});
In Controllers, use the [ResponseDescription]
attribute to define descriptions for specific responses:
[HttpGet("{id:guid}")]
[ProducesResponseType<Book>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ResponseDescription("The requested book")]
[ResponseDescription("The book was not found", StatusCodes.Status404NotFound)]
public IActionResult GetBook(Guid id)
For Minimal APIs, you can add descriptions with the ResponseDescription
extension method:
.MapGet("/{bookId:guid}", (Guid bookId) =>
{
// Get the book by ID
})
.Produces<Book>()
.Produces(StatusCodes.Status404NotFound)
.ResponseDescription("The requested book")
.ResponseDescription("The book was not found", StatusCodes.Status404NotFound);
Set server URLs for your OpenAPI document:
builder.Services.AddOpenApi(options =>
{
// Add server URLs directly to the OpenAPI document
options.AddServers("https://api.example.com", "https://api2.example.com");
// Or add servers using OpenApiServer
options.AddServers(
{
new OpenApiServer
{
Url = "https://api.example.com"
},
new OpenApiServer
{
Url = "https://api2.example.com",
}
});
// Adds the server URL dynamically using the HttpContext.
options.AddServerFromRequest();
});
Note
Any AddServers
method replaces all existing server URLs in the OpenAPI document
Note
To use AddServerFromRequest
, ensure IHttpContextAccessor
is registered in the service collection.
builder.Services.AddOpenApi(options =>
{
// Adds the request body parameter name to the OpenAPI operation
options.AddRequestBodyParameterName();
});
If you use the Microsoft.Extensions.ApiDescription.Server
package with build-time document generation, you may want to use the static BuildHelper
class, which provides a property that indicates whether the current execution context is the document generator. You can use it as follows:
using static APIWeaver.BuildHelper;
...
if (!IsGenerationContext)
{
builder.Services.AddSingleton<IMyService, MyService>();
}
var app = builder.Build();
if (IsGenerationContext)
{
app.Run();
}
More features are coming soon...