DotNetOpenApiExtract 0.3.0

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global DotNetOpenApiExtract --version 0.3.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local DotNetOpenApiExtract --version 0.3.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=DotNetOpenApiExtract&version=0.3.0
                    
nuke :add-package DotNetOpenApiExtract --version 0.3.0
                    

DotNetOpenApiExtract

NuGet License: MIT

CLI tool that extracts OpenAPI specifications from compiled .NET assemblies (DLL + XML docs) using static reflection — no application startup required.

Installation

dotnet tool install -g DotNetOpenApiExtract

Usage

dotnet openapi-extract --assembly bin/Debug/net9.0/MyApi.dll --output openapi.json

Why

Standard OpenAPI generation tools (swagger tofile, Microsoft.AspNetCore.OpenApi) require the application to fully start — which means a real database, message queues, external APIs, background services, and all environment variables must be available. Without infrastructure, the app crashes and the spec is never generated.

DotNetOpenApiExtract solves this by reading metadata directly from the compiled DLL via MetadataLoadContext. It never executes any code from your assembly. All it needs is the build output directory.

This means you can generate OpenAPI specs:

  • In CI/CD without any infrastructure
  • On developer machines without Docker or databases running
  • From any .NET version (6, 7, 8, 9, 10) assembly

CLI Parameters

Parameter Required Default Description
--assembly <path> yes Path to the compiled DLL
--output <path> no swagger.json Output file path
--format <json\|yaml> no json Output format
--title <string> no assembly name API title in the info block
--version <string> no v1 API version in the info block
--description <string> no API description
--xml <path> no auto-detect Path to XML documentation file
--source <path> no Entry-point source file (usually auto-detected)
--source-root <dir> no auto-detect Project root for Roslyn analysis of Program.cs
--naming-policy <policy> no camelCase camelCase, snake_case_lower, snake_case_upper, kebab-case-lower, kebab-case-upper, preserve
--enum-as-string no false Serialize enums as strings
--path-base-emission <mode> no prefix How to emit UsePathBase: prefix (prepend to paths) or servers (add to servers[])
--openapi-version <3.0\|3.1\|3.2> no 3.0 OpenAPI specification version
--exclude-path <prefix> no Exclude paths by prefix (repeatable)
--contact-name <string> no info.contact.name
--contact-email <string> no info.contact.email
--contact-url <url> no info.contact.url
--license-name <string> no info.license.name
--license-url <url> no info.license.url
--terms-of-service <url> no info.termsOfService
--server <url> no Server URL in servers[] (repeatable)

Validation flags

Parameter Required Default Description
--validate no off Enable validation (47 rules, errors block CI via exit 1)
--skip-rule <id> no Disable a rule (repeatable). Unknown IDs print warning to stderr
--warn-rule <id> no Demote error → warning (repeatable)
--error-rule <id> no Promote warning → error (repeatable)
--enable-rule <id> no Enable an off-by-default rule (repeatable)
--strict no false Treat all warnings as errors (CI-strict mode)
--min-description-length <N> no 5 Minimum length for description-rule checks
--exclude-validation-path <prefix> no Path prefixes skipped by operation.has-error-response and operation.success-response rules only (repeatable)
--validation-report <path> no Write JSON report to file (else printed to stdout)

Validation

Running --validate checks the extracted spec against 47 completeness rules — 26 errors + 16 warnings always-on + 5 warnings off-by-default.

Severity Count Exit code When to use
Error 26 1 OpenAPI-spec MUST violations, broken codegen
Warning 16 0 Industry best-practice (Spectral / Redocly consensus)
Warning (off-by-default) 5 0 (disabled) Opt-in via --enable-rule: spec.servers-defined, tag.description, component.no-unused, spec.no-eval-in-markdown, spec.no-script-tags-in-markdown

Typical CI usage:

# Block on errors, ignore warnings
dotnet openapi-extract --assembly bin/Debug/net9.0/MyApi.dll --validate

# Strict: block on any violation including warnings
dotnet openapi-extract --assembly bin/Debug/net9.0/MyApi.dll --validate --strict

# Skip a noisy rule
dotnet openapi-extract --assembly bin/Debug/net9.0/MyApi.dll --validate --skip-rule schema.required-consistency

# JSON report for tooling/agents
dotnet openapi-extract --assembly bin/Debug/net9.0/MyApi.dll --validate --validation-report report.json

Standalone validation — validate an existing spec file without extracting:

dotnet openapi-extract validate --spec openapi.json --validation-report report.json

All severity/skip/enable flags apply to both modes. Run dotnet openapi-extract --help and dotnet openapi-extract validate --help for the full rule list with per-rule severities.

What It Extracts

  • Controllers ([ApiController], ControllerBase inheritance)
  • Routes ([Route], [HttpGet], [HttpPost], etc.) with full template resolution
  • Parameters ([FromRoute], [FromQuery], [FromBody], [FromHeader], [FromForm]) with [ApiController] inference
  • Responses ([ProducesResponseType], [SwaggerResponse]) with return type inference
  • Schemas from DTO classes — primitives, nullable, collections, dictionaries, enums, generics, inheritance, self-referencing types
  • Validation attributes ([Required], [StringLength], [Range], [RegularExpression], etc.)
  • JSON attributes ([JsonPropertyName], [JsonIgnore], [JsonRequired])
  • Swagger annotations ([SwaggerOperation], [SwaggerParameter], [SwaggerTag], [SwaggerSchema])
  • XML documentation (<summary>, <remarks>, <param>, <response>)
  • Nullable reference types via NRT attribute analysis
  • Description fallback chains: Swagger attrs > [Description] > XML docs
  • [Obsolete]deprecated: true on operations, schemas, enums
  • API versioning ([ApiVersion], [MapToApiVersion], [ApiVersionNeutral]) as x-api-version extension
  • Rate limiting ([EnableRateLimiting], [DisableRateLimiting]) as x-rate-limit-* extensions
  • Response caching ([ResponseCache], [OutputCache]) as Cache-Control header description
  • Well-known [JsonConverter] types (JsonStringEnumConverter, IsoDateTimeConverter, UnixDateTimeConverter, StringEnumConverter, etc.) mapped via built-in registry
  • Per-endpoint security from [Authorize] / [AllowAnonymous] / [Authorize(AuthenticationSchemes=...)]

From Program.cs via Roslyn (when sources are available):

  • Security schemes (AddSecurityDefinition, AddJwtBearer, AddSecurityRequirement) — including lambda-factory form
  • UsePathBase("/prefix") — prepended to paths or emitted as servers[].url
  • AddProblemDetails() — auto-injects default 400 / 422 / 500 responses with RFC 7807 ProblemDetails schema
  • JSON serializer options (ConfigureHttpJsonOptions / AddJsonOptions): PropertyNamingPolicy, DictionaryKeyPolicy, DefaultIgnoreCondition, NumberHandling, global Converters.Add(...)
  • Global response headers from middleware (app.Use(...), UseMiddleware<T>) — Response.Headers.Append/Add/TryAdd and indexer assignments
  • Global [Consumes] / [Produces] from MVC filter registrations
  • Document-level tags with descriptions + externalDocs from c.AddTag(...)
  • FQN-prefixed types and enums (new Microsoft.OpenApi.OpenApiSecurityScheme { Type = Microsoft.OpenApi.SecuritySchemeType.ApiKey })
  • In-project const string values via SemanticModel.GetConstantValue

For the complete catalog of 650+ supported attributes and constructs, see OpenAPI Attributes Catalog.

Limitations

What Why
IOperationFilter, IDocumentFilter, ISchemaFilter Arbitrary C# code executed at runtime — cannot be analyzed statically
Conventional routing (MapControllerRoute) Routes defined in runtime code, not in attributes
Minimal API endpoints (app.MapGet(...)) Endpoints defined in Program.cs, not via controllers
Unknown [JsonConverter] types Arbitrary runtime code — falls back to default schema. Well-known converters are recognized via built-in registry
[ModelBinder] custom binding Runtime behavior, not interpretable statically
Runtime Swashbuckle filters Any filter that modifies the document at runtime is invisible to static analysis

Runtime-only Program.cs patterns

When analyzing Program.cs via Roslyn for security schemes, response headers, global options, etc., the tool recognizes common patterns but cannot resolve values known only at runtime.

Pattern Example Why
IConfiguration values Type = config["Auth:Scheme"] Value comes from appsettings.json / env vars at runtime
Conditional registration if (env.IsDevelopment()) services.AddX() Depends on runtime environment
DI-factory registration services.AddScoped<ISchemeProvider>(sp => sp.GetRequiredService<X>()) Resolved from runtime DI graph
Assembly-scan plugin discovery services.Scan(...).AddClasses(...) Types discovered by runtime reflection
Runtime interpolation Headers.Append($"X-{variable}", ...) Variable value known only at runtime

These patterns are skipped silently (or with a warning to stderr). If your project relies heavily on runtime-resolved configuration, consider a Swashbuckle CLI tofile approach which executes the assembly partially instead of analyzing it statically.

Dependencies

Package Version Purpose
Microsoft.OpenApi 3.5.0 OpenAPI document model, JSON/YAML serialization, validation
Microsoft.OpenApi.YamlReader 3.5.0 YAML output support
System.Reflection.MetadataLoadContext 10.0.5 Load DLLs without executing code, read attributes and types
Microsoft.CodeAnalysis.CSharp 4.11.0 Roslyn parsing of Program.cs for runtime-configuration extraction
System.CommandLine 2.0.5 CLI argument parsing

Does not depend on: ASP.NET Core, Swashbuckle, Entity Framework, or any infrastructure packages.

Requirements

  • .NET 10 SDK (to run the tool)
  • The target assembly's build output directory with all reference DLLs (the tool needs them to resolve types)

Building

dotnet build
dotnet test

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.15.0 99 5/12/2026
0.14.0 100 4/30/2026
0.12.0 89 4/30/2026
0.11.0 110 4/29/2026
0.10.0 110 4/24/2026
0.9.0 97 4/22/2026
0.8.0 96 4/22/2026
0.7.0 101 4/20/2026
0.6.0 111 4/19/2026
0.5.0 105 4/19/2026
0.4.0 101 4/19/2026
0.3.0 95 4/19/2026
0.2.0 105 4/18/2026
0.1.0 124 3/24/2026