Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
OpenAPI/Swagger integration for ASP.NET Core. Microsoft.AspNetCore.OpenApi is the recommended first-party approach for
.NET 9+ and is the default in new project templates. Swashbuckle is no longer actively maintained; existing projects
using Swashbuckle should plan migration. NSwag remains an alternative for client generation and advanced scenarios.
Scope
Microsoft.AspNetCore.OpenApi setup and multi-document configuration
Document, operation, and schema transformers
Swashbuckle migration steps and filter-to-transformer mapping
NSwag document generation and client generation
OpenAPI 3.1 support in .NET 10
Out of scope
Minimal API endpoint patterns (route groups, filters, TypedResults) -- see [skill:dotnet-minimal-apis]
API versioning strategies -- see [skill:dotnet-api-versioning]
Authentication and authorization -- see [skill:dotnet-api-security]
Cross-references: [skill:dotnet-minimal-apis] for endpoint patterns that generate OpenAPI metadata,
[skill:dotnet-api-versioning] for versioned OpenAPI documents.
Microsoft.AspNetCore.OpenApi (Recommended)
Microsoft.AspNetCore.OpenApi is the first-party OpenAPI package for ASP.NET Core 9+ and is included by default in new
project templates. .NET 10 adds OpenAPI 3.1 support with JSON Schema draft 2020-12 compliance.
Basic Setup
// Microsoft.AspNetCore.OpenApi -- included by default in .NET 9+ project templates// If not present, add: <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.*" />// Version must match the project's target framework major version
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // Serves /openapi/v1.json
}
```json
### Multiple Documents
Generate separate OpenAPI documents per API version or functional group:
```csharp
builder.Services.AddOpenApi("v1", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_0;
});
builder.Services.AddOpenApi("v2", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});
var app = builder.Build();
app.MapOpenApi(); // Serves /openapi/v1.json and /openapi/v2.json
```json
---
Document transformers modify the generated OpenAPI document after it built. Use them to server information, security schemes, custom metadata.
```csharp
:
{
{
document.Components ??= OpenApiComponents();
document.Components.SecuritySchemes[] = OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = ,
BearerFormat = ,
Description =
};
document.SecurityRequirements.Add( OpenApiSecurityRequirement
{
[] = Array.Empty<>()
});
Task.CompletedTask;
}
}
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer<SecuritySchemeTransformer>();
});
```text
For simple transformations, use the lambda overload:
```csharp
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info = OpenApiInfo
{
Title = ,
Version = ,
Description = ,
Contact = OpenApiContact
{
Name = ,
Email =
}
};
Task.CompletedTask;
});
});
```text
---
{
{
deprecatedAttr = context.Description.ActionDescriptor
.EndpointMetadata
.OfType<ObsoleteAttribute>()
.FirstOrDefault();
(deprecatedAttr )
{
operation.Deprecated = ;
operation.Description = ;
}
Task.CompletedTask;
}
}
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer<DeprecationTransformer>();
});
```text
---
Customize how .NET types map to OpenAPI schemas schema transformers:
```csharp
builder.Services.AddOpenApi(options =>
{
options.AddSchemaTransformer((schema, context, ct) =>
{
(context.JsonTypeInfo.Type == (ProductDto))
{
schema.Example = OpenApiObject
{
[] = OpenApiInteger(),
[] = OpenApiString(),
[] = OpenApiDouble()
};
}
Task.CompletedTask;
});
});
```text
Use fluent methods endpoint builders to provide richer OpenAPI metadata:
```csharp
products.MapGet(, GetProductById)
.WithName()
.WithSummary()
.WithDescription()
.WithTags()
.Produces<Product>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status404NotFound);
```text
---
Swashbuckle (`Swashbuckle.AspNetCore`) no longer actively maintained. It does support OpenAPI . Existing projects should plan migration to `Microsoft.AspNetCore.OpenApi`.
**When Swashbuckle still needed:** Projects .NET that cannot upgrade to .NET +, projects that depend Swashbuckle-= Version= /> -->
<!-- <PackageReference Include= Version= /> -->
```xml
Replace service registration:
```csharp
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc(, OpenApiInfo { Title = , Version = });
});
builder.Services.AddOpenApi();
```text
Replace middleware:
```csharp
app.UseSwagger();
app.UseSwaggerUI();
app.MapOpenApi();
```json
For Swagger UI, a standalone UI package use Scalar:
```csharp
app.MapScalarApiReference();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(, );
});
```json
Migrate Swashbuckle filters to transformers:
| Swashbuckle concept | Built- replacement |
|---------------------|---------------------|
| `IDocumentFilter` | `IOpenApiDocumentTransformer` |
| `IOperationFilter` | `IOpenApiOperationTransformer` |
| `ISchemaFilter` | Schema transformers via `AddSchemaTransformer` |
| `[SwaggerOperation]` | `.WithSummary()`, `.WithDescription()` |
| `[SwaggerResponse]` | `.Produces<T>()`, `TypedResults` |
---
NSwag an alternative OpenAPI toolchain that includes document generation, ;
app = builder.Build();
app.UseOpenApi();
app.UseSwaggerUi();
```json
NSwag generates typed C
```bash
dotnet tool install -- NSwag.ConsoleCore
nswag openapi2csclient /input:https:
/output:GeneratedClient.cs \
/: \
/:
```
**:** `` . . .
---
## 3.1 (. 10)
. 10 3.1 2020-12 . 3.0:
- ** :** `: ["", ""]` `: `
- ** :** /
- **:** -
- ** :** 2020-12
```
( =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});
```text
**Gotcha:** Swashbuckle does support OpenAPI . Projects requiring features must migrate to `Microsoft.AspNetCore.OpenApi`.
---
**Do pin mismatched major versions of `Microsoft.AspNetCore.OpenApi`** -- the package version must match the project
## Document Transformers
is
add
or
### IOpenApiDocumentTransformer
public
sealed
class
SecuritySchemeTransformer
IOpenApiDocumentTransformer
public Task TransformAsync(
OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken)
new
"Bearer"
new
"bearer"
"JWT"
"JWT Bearer token authentication"
new
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
}
string
return
// Register the transformer
### Lambda Document Transformers
new
"Products API"
"v1"
"Product catalog management API"
new
"API Support"
"api-support@example.com"
return
## Operation Transformers
Operation transformers modify individual operations (endpoints) in the OpenAPI document. Use them to add per-operation metadata, examples, or conditional logic.
```csharp
publicsealedclass DeprecationTransformer : IOpenApiOperationTransformer
public Task TransformAsync(
OpenApiOperation operation,
OpenApiOperationTransformerContext context,
CancellationToken cancellationToken)
var
if
is
not
null
true
$"DEPRECATED: {deprecatedAttr.Message}"
return
## Schema Customization
using
// Add example values for known types
if
typeof
new
"id"
new
1
"name"
new
"Widget"
"price"
new
19.99
return
### Enriching Endpoint Metadata
on
"/{id:int}"
"GetProductById"
"Get a product by its ID"
"Returns the product details for the specified ID, or 404 if not found."
"Products"
## Swashbuckle Migration
is
not
3.1
is
on
8
9
or
on
specific features (SwaggerUI with deep customization, ISchemaFilter pipelines) may continueusing Swashbuckle while planning migration.
### Migration Steps
1. Remove Swashbuckle packages:
```xml
<!-- Remove these -->
<!-- <PackageReference Include
"Swashbuckle.AspNetCore"
"..."
"Swashbuckle.AspNetCore.Annotations"
"..."
1.
// Before (Swashbuckle)
"v1"
new
"My API"
"v1"
// After (Microsoft.AspNetCore.OpenApi)
1.
// Before (Swashbuckle)
// After (built-in)
// Serves raw OpenAPI JSON at /openapi/v1.json
1.
add
or
// Option 1: Scalar (modern, built-in support in .NET 10)
// <PackageReference Include="Aspire.Dashboard.Components.Scalar" ... /> or use MapScalarApiReference
client generation (C#, TypeScript), and a UI. It is useful when you need generated API clients orwhen integrating with non-.NET consumers.
### Document Generation
```csharp
// <PackageReference Include="NSwag.AspNetCore" Version="14.*" />
builder.Services.AddOpenApiDocument(options =>
{
options.Title = "Products API";
options.Version = "v1";
options.DocumentName = "v1";
})
// Explicitly set version if needed (3.1 is default in .NET 10)
not
3.1
3.1
## Agent Gotchas
1.
not
's target framework major version. Do not mix incompatible OpenAPI stacks (e.g., Swashbuckle + built-in) in the same project.
2. **Do not recommend Swashbuckle for new .NET 9+ projects** -- it is no longer actively maintained. Use the built-in `Microsoft.AspNetCore.OpenApi` instead.
3. **Do not say Swashbuckle is "deprecated"** -- it is not formally deprecated, but it is no longer actively maintained. Say "preferred" or "recommended" when referring to the built-in alternative.
4. **Do not forget the Swagger UI replacement** -- `MapOpenApi()` only serves the raw JSON spec. Add Scalar, Swagger UI standalone, or another UI separately.
5. **Do not mix Swashbuckle and built-in OpenAPI in the same project** -- they generate conflicting documents. Choose one approach.
6. **Do not hardcode ASP.NET shared-framework package versions** -- packages like `Microsoft.AspNetCore.OpenApi` must match the project TFM major version.
---
## Prerequisites
- .NET 9.0+ for `Microsoft.AspNetCore.OpenApi` (included in default project templates)
- .NET 10.0 for OpenAPI 3.1, JSON Schema draft 2020-12, and Scalar integration
- `NSwag.AspNetCore` (optional) for NSwag-based generation and UI
- `Swashbuckle.AspNetCore` (legacy) for existing projects not yet migrated
---
## References
- [OpenAPI in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/overview?view=aspnetcore-10.0)
- [Microsoft.AspNetCore.OpenApi](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi?view=aspnetcore-10.0)
- [OpenAPI Document Transformers](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi?view=aspnetcore-10.0)
- [Migrate from Swashbuckle](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi?view=aspnetcore-10.0#migrate-from-swashbuckle)
- [NSwag](https://github.com/RicoSuter/NSwag)
- [Scalar API Reference](https://github.com/ScalarHQ/scalar)
Code Navigation (Serena MCP)
Primary approach: Use Serena symbol operations for efficient code navigation:
Find definitions: serena_find_symbol instead of text search
Understand structure: serena_get_symbols_overview for file organization
Track references: serena_find_referencing_symbols for impact analysis
Precise edits: serena_replace_symbol_body for clean modifications
When to use Serena vs traditional tools:
Use Serena: Navigation, refactoring, dependency analysis, precise edits
Use Read/Grep: Reading full files, pattern matching, simple text operations
Fallback: If Serena unavailable, traditional tools work fine