NSwag provides a comprehensive framework for generating OpenAPI documents from .NET applications. The generation system is built around extensible processors and settings that allow for deep customization of the generated specifications.
public interface IOpenApiDocumentGenerator
{
Task<OpenApiDocument> GenerateAsync(string documentName);
}The primary generator for ASP.NET Core applications.
public class AspNetCoreOpenApiDocumentGenerator : IOpenApiDocumentGenerator
{
public AspNetCoreOpenApiDocumentGenerator(AspNetCoreOpenApiDocumentGeneratorSettings settings);
public Task<OpenApiDocument> GenerateAsync(string documentName);
public Task<OpenApiDocument> GenerateForControllerAsync(Type controllerType);
public Task<OpenApiDocument> GenerateForControllerActionAsync(Type controllerType, string actionName);
}Configuration for ASP.NET Core document generation.
public class AspNetCoreOpenApiDocumentGeneratorSettings : OpenApiDocumentGeneratorSettings
{
// Assembly and reflection settings
public IAssemblyLoader AssemblyLoader { get; set; }
public ITypeNameGenerator TypeNameGenerator { get; set; }
public IReflectionService ReflectionService { get; set; }
// Generation behavior
public bool UseRouteNameAsOperationId { get; set; }
public bool RequireParametersWithoutDefault { get; set; }
public AspNetCoreOperationNameGenerator OperationNameGenerator { get; set; }
// API Explorer settings
public bool UseDocumentProvider { get; set; }
public string DocumentName { get; set; }
public string ApiGroupNames { get; set; }
// Processors
public IList<IOperationProcessor> OperationProcessors { get; }
public IList<IDocumentProcessor> DocumentProcessors { get; }
}using NSwag.Generation.AspNetCore;
// Create settings
var settings = new AspNetCoreOpenApiDocumentGeneratorSettings
{
Title = "My Web API",
Version = "1.0.0",
Description = "RESTful API for my application"
};
// Configure additional options
settings.RequireParametersWithoutDefault = true;
settings.UseRouteNameAsOperationId = false;
// Generate document
var generator = new AspNetCoreOpenApiDocumentGenerator(settings);
var document = await generator.GenerateAsync("v1");
// Use the document
string json = document.ToJson();Generator for legacy ASP.NET Web API applications.
public class WebApiOpenApiDocumentGenerator : IOpenApiDocumentGenerator
{
public WebApiOpenApiDocumentGenerator(WebApiOpenApiDocumentGeneratorSettings settings);
public Task<OpenApiDocument> GenerateAsync(string documentName);
public Task<OpenApiDocument> GenerateForControllerAsync(string controllerName);
public Task<OpenApiDocument> GenerateForControllersAsync(IEnumerable<string> controllerNames);
}public class WebApiOpenApiDocumentGeneratorSettings : OpenApiDocumentGeneratorSettings
{
public IList<Type> ControllerTypes { get; set; }
public string DefaultUrlTemplate { get; set; }
public bool IsAspNetCore { get; set; }
public IAssemblyLoader AssemblyLoader { get; set; }
}Base settings class for all document generators.
public class OpenApiDocumentGeneratorSettings : JsonSchemaGeneratorSettings
{
// Document metadata
public string Title { get; set; }
public string Description { get; set; }
public string Version { get; set; }
public string DocumentName { get; set; }
// Schema generation
public OpenApiSchemaGenerator SchemaGenerator { get; set; }
// Processors
public IList<IOperationProcessor> OperationProcessors { get; }
public IList<IDocumentProcessor> DocumentProcessors { get; }
// Additional settings
public bool AddMissingPathParameters { get; set; }
public PostProcessAction PostProcess { get; set; }
}Generates JSON schemas for OpenAPI specifications.
public class OpenApiSchemaGenerator : JsonSchemaGenerator
{
public OpenApiSchemaGenerator(OpenApiDocumentGeneratorSettings settings);
public Task<JsonSchema> GenerateWithReferenceAsync<T>();
public Task<JsonSchema> GenerateWithReferenceAsync(Type type, bool mayBeNull = false);
public void ApplySchemaProcessors(JsonSchema schema, Type type, JsonSchemaResolver schemaResolver);
}The processor framework allows for extensible customization of document generation.
Process the entire document after generation.
public interface IDocumentProcessor
{
void Process(DocumentProcessorContext context);
}
public class DocumentProcessorContext
{
public OpenApiDocument Document { get; }
public OpenApiDocumentGeneratorSettings Settings { get; }
public JsonSchemaResolver SchemaResolver { get; }
public OpenApiSchemaGenerator SchemaGenerator { get; }
}Process individual operations during generation.
public interface IOperationProcessor
{
bool Process(OperationProcessorContext context);
}
public class OperationProcessorContext
{
public OpenApiDocument Document { get; }
public OperationDescription OperationDescription { get; }
public OpenApiDocumentGeneratorSettings Settings { get; }
public JsonSchemaResolver SchemaResolver { get; }
public OpenApiSchemaGenerator SchemaGenerator { get; }
public Type ControllerType { get; }
public MethodInfo MethodInfo { get; }
}Extended context for ASP.NET Core-specific processing.
public class AspNetCoreOperationProcessorContext : OperationProcessorContext
{
public ApiDescription ApiDescription { get; }
public IApiDescriptionGroupCollectionProvider ApiExplorer { get; }
public string HttpMethod { get; }
public string Route { get; }
}public class DocumentTagsProcessor : IDocumentProcessor
{
public void Process(DocumentProcessorContext context);
}
public class DocumentExtensionDataProcessor : IDocumentProcessor
{
public void Process(DocumentProcessorContext context);
}
public class SecurityDefinitionAppender : IDocumentProcessor
{
public SecurityDefinitionAppender(string name, OpenApiSecurityScheme securityScheme);
public void Process(DocumentProcessorContext context);
}public class OperationSummaryAndDescriptionProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context);
}
public class OperationTagsProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context);
}
public class OperationExtensionDataProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context);
}
public class OperationSecurityScopeProcessor : IOperationProcessor
{
public string Name { get; }
public IEnumerable<string> Scopes { get; }
public OperationSecurityScopeProcessor(string name);
public OperationSecurityScopeProcessor(string name, IEnumerable<string> scopes);
public bool Process(OperationProcessorContext context);
}Control how operation IDs and client method names are generated.
public interface IOperationNameGenerator
{
string GetClientName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
string GetOperationName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
}public class SingleClientFromOperationIdOperationNameGenerator : IOperationNameGenerator
{
public string GetClientName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
public string GetOperationName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
}
public class MultipleClientsFromOperationIdOperationNameGenerator : IOperationNameGenerator
{
public string GetClientName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
public string GetOperationName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
}
public class MultipleClientsFromFirstTagAndOperationIdGenerator : IOperationNameGenerator
{
public string GetClientName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
public string GetOperationName(OpenApiDocument document, string path, string httpMethod, OpenApiOperation operation);
}public class CustomDocumentProcessor : IDocumentProcessor
{
public void Process(DocumentProcessorContext context)
{
context.Document.Info.Title = "Customized " + context.Document.Info.Title;
// Add custom extension data
context.Document.ExtensionData["x-custom-property"] = "custom-value";
}
}
// Register the processor
settings.DocumentProcessors.Add(new CustomDocumentProcessor());public class CustomOperationProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context)
{
// Add custom tags based on controller name
var controllerName = context.ControllerType.Name.Replace("Controller", "");
context.OperationDescription.Operation.Tags.Add(controllerName);
return true; // Continue processing
}
}
// Register the processor
settings.OperationProcessors.Add(new CustomOperationProcessor());var settings = new AspNetCoreOpenApiDocumentGeneratorSettings
{
Title = "My Advanced API",
Version = "2.0.0",
Description = "Advanced API with custom processing",
// Schema settings
DefaultReferenceNameGenerator = type => type.Name,
GenerateAbstractProperties = true,
// Operation settings
RequireParametersWithoutDefault = true,
UseRouteNameAsOperationId = false,
};
// Add security scheme
settings.DocumentProcessors.Add(new SecurityDefinitionAppender("JWT", new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "JWT Authorization header using the Bearer scheme."
}));
// Add custom processors
settings.DocumentProcessors.Add(new CustomDocumentProcessor());
settings.OperationProcessors.Add(new CustomOperationProcessor());
// Set operation name generator
settings.OperationNameGenerator = new MultipleClientsFromFirstTagAndOperationIdGenerator();
var generator = new AspNetCoreOpenApiDocumentGenerator(settings);
var document = await generator.GenerateAsync("v1");