-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
AspNetCore Middleware
-
Package: NSwag.AspNetCore
- .NETStandard 1.6 , .NET Standard 2.0, .NET Core and .NET 4.5.1
- Supports ASP.NET Core 2.1 - 5.0
The NuGet package provides extension methods to register the NSwag ASP.NET Core services and middlewares:
The middlewares are based on the AspNetCoreOpenApiDocumentGenerator class which generates OpenAPI/Swagger specifications from ASP.NET Core controllers with the ASP.NET Core API Explorer.
To use the middlewares, open Startup.cs
and add the following code to ConfigureServices()
(full samples below):
-
services.AddOpenApiDocument(configure)
(OpenAPI v3.0.0) -
services.AddSwaggerDocument(configure)
(Swagger v2.0): Adds a new OpenAPI/Swagger document registration to the DI system- The default document name is
v1
- The
document
instance implements the AspNetCoreOpenApiDocumentGeneratorSettings - To configure multiple documents, just call the methods multiple times and define a
DocumentName
per document:
- The default document name is
services.AddOpenApiDocument(document => document.DocumentName = "a");
services.AddSwaggerDocument(document => document.DocumentName = "b");
In Startup.Configure()
:
-
app.UseOpenApi(configure)
: Adds the OpenAPI/Swagger document generator middleware (serves openapi.json/swagger.json).- The default route is
/swagger/{documentName}/swagger.json
; when using the{documentName}
placeholder in thePath
setting, multiple documents can be served
- The default route is
-
app.UseSwaggerUi3(configure)
: -
app.UseReDoc(configure)
: Adds only the Swagger UI or ReDoc web UI- The default UI route in
Path
is/swagger
which - in the case of Swagger UI - serves one UI with all available documents - The default document route in
DocumentPath
is/swagger/{documentName}/swagger.json
- The default UI route in
app.UseOpenApi(); // serve documents (same as app.UseSwagger())
app.UseSwaggerUi3(); // serve Swagger UI
app.UseReDoc(); // serve ReDoc UI
Sample projects:
- Sample project: Simple Config (.NET Core 2.1)
- Sample project: Advanced Config (.NET Core 2.0)
- Sample project: API Versioning Config (.NET Core 2.0)
- Sample project: Reverse Proxy Config (.NET Core 2.1)
First, you need to install the required NSwag NuGet packages.
- NSwag.AspNetCore
- If you are using .NET Core >= v2.1 and < 3.0 with new API Explorer based generator, you may need to set the CompatibilityVersion
- If you are using .NET Core <= v2.0 or ASP.NET Core with full .NET Framework, you may need to muanually install Microsoft.AspNetCore.StaticFiles
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options =>
{
// Use camel case properties in the serializer and the spec (optional)
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Use string enums in the serializer and the spec (optional)
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});
// Add OpenAPI/Swagger document
services.AddOpenApiDocument(); // registers a OpenAPI v3.0 document with the name "v1" (default)
// services.AddSwaggerDocument(); // registers a Swagger v2.0 document with the name "v1" (default)
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
// Add OpenAPI/Swagger middlewares
app.UseOpenApi(); // Serves the registered OpenAPI/Swagger documents by default on `/swagger/{documentName}/swagger.json`
app.UseSwaggerUi3(); // Serves the Swagger UI 3 web ui to view the OpenAPI/Swagger documents by default on `/swagger`
// Register the middleware before UseRouting()
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
The AspNetCoreOpenApiDocumentGenerator class provides lots of customization and extension possibilities.
Use the ApiGroupNames
setting to select the operation version filter:
services.AddOpenApiDocument(document =>
{
document.DocumentName = "v1";
document.ApiGroupNames = new [] { "1" };
});
services.AddOpenApiDocument(document =>
{
document.DocumentName = "v2";
document.ApiGroupNames = new [] { "2" };
});
The API versioning has to be configured like this:
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = new UrlSegmentApiVersionReader();
})
.AddMvcCore()
.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "VVV";
options.SubstituteApiVersionInUrl = true;
});
For more information have a look at this PR.
For more information on the GroupNameFormat
property, have a look at this comment.
You can post process a generated document with the PostProcess
setting from AddSwaggerDocument()
or UseOpenApi()
or use a custom Document Processor or Operation Processor (recommended).
services.AddSwaggerDocument(document =>
{
document.PostProcess = d =>
{
d.Info.Title = "Hello world!";
};
});
Caution: Only use PostProces
from UseOpenApi()
to transform the document related to the request. Other modifications should be done with a custom Document Processor or Operation Processor which is added in AddSwaggerDocument(document => document.DocumentProcessors)
or AddSwaggerDocument(document => document.PostProcess = ...)
. The post processing in UseOpenApi()
will not be called from the NSwag CLI or MSBuild, i.e. only when served via HTTP!
app.UseOpenApi(settings =>
{
settings.PostProcess = (document, request) =>
{
document.Host = request...
};
});
The PostProcess
and TransformToExternalPath
config might be needed when serving through a reverse proxy. See sample:
See sample project: Advanced Config (.NET Core 2.0)
TODO: Add PKCE Auth: https://github.com/RicoSuter/NSwag/issues/2375#issuecomment-554394786
Ensure that the page 'oauth2-redirect.html' is allowed as Redirect URL on the Swagger UI route (e.g. https://localhost:5001/swagger/oauth2-redirect.html
).
// Add security definition and scopes to document
services.AddOpenApiDocument(document =>
{
document.AddSecurity("bearer", Enumerable.Empty<string>(), new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.OAuth2,
Description = "My Authentication",
Flow = OpenApiOAuth2Flow.Implicit,
Flows = new OpenApiOAuthFlows()
{
Implicit = new OpenApiOAuthFlow()
{
Scopes = new Dictionary<string, string>
{
{ "read", "Read access to protected resources" },
{ "write", "Write access to protected resources" }
},
AuthorizationUrl = "https://localhost:44333/core/connect/authorize",
TokenUrl = "https://localhost:44333/core/connect/token"
},
}
});
document.OperationProcessors.Add(
new AspNetCoreOperationSecurityScopeProcessor("bearer"));
// new OperationSecurityScopeProcessor("bearer"));
);
Define the configuration for the Swagger UI 3's OAuth2 client in Startup.Configure()
:
app.UseSwagger();
app.UseSwaggerUi3(settings =>
{
settings.OAuth2Client = new OAuth2ClientSettings
{
ClientId = "foo",
ClientSecret = "bar",
AppName = "my_app",
Realm = "my_realm",
AdditionalQueryStringParameters =
{
{ "foo", "bar" }
}
};
});
- OAuth2Client: Defines the settings for the OAuth2 client (i.e. the Swagger UI frontend)
- SecurityDefinitionAppender: Adds a security definition to the OpenAPI specification
- OperationSecurityScopeProcessor (Reflection based): Scans the AuthorizeAttribute attributes on controllers and action methods and adds the given roles as security scopes to the OpenAPI specification
-
AspNetCoreOperationSecurityScopeProcessor (ASP.NET Core metadata based): For ASP.NET Core 2.2 it is recommended to use the
AspNetCoreOperationSecurityScopeProcessor
instead of theOperationSecurityScopeAppender
as it will use the metadata exposed by ASP.NET Core and should produce better results.
services.AddOpenApiDocument(document =>
{
document.AddSecurity("apikey", Enumerable.Empty<string>(), new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "api_key",
In = OpenApiSecurityApiKeyLocation.Header
});
document.OperationProcessors.Add(
new AspNetCoreOperationSecurityScopeProcessor("apikey"));
// new OperationSecurityScopeProcessor("apikey"));
});
You achieve this by telling NSwag to use JWT token authorization.
This applies the security scheme to the whole document:
services.AddMvc();
services.AddOpenApiDocument(document =>
{
document.AddSecurity("Bearer", Enumerable.Empty<string>(), new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT",
Description = "Type into the textbox: {your JWT token}."
});
document.OperationProcessors.Add(
new AspNetCoreOperationSecurityScopeProcessor("Bearer"));
// new OperationSecurityScopeProcessor("Bearer"));
});
As an alternative, this applies the security scheme only to the specific operations that require it:
services.AddOpenApiDocument(document =>
{
document.AddSecurity("Bearer", new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT",
Description = "Type into the textbox: {your JWT token}."
});
document.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("Bearer"));
});
To let the user enter the client ID and client secret, use the following code for now:
new OAuth2ClientSettings
{
ClientId = "\" prompt('Please enter ClientId: ') \"",
ClientSecret = "\" prompt('Please enter ClientSecret: ') \""
}
v13 automatically handles common proxy routes, paths and headers, see this PR
When the application is hosted as an IIS virtual application or behind a (reverse) proxy, the request path to swagger.json is missing the path of the virtual application. For example, https://example.com/myapi/swagger will make a request to https://example.com/swagger/v1/swagger.json
To work around this, the request can be intercepted to modify the path, as demonstrated in the Reverse Proxy Config (.NET Core 2.1) sample project.
app.UseSwaggerUi3(config => config.TransformToExternalPath = (internalUiRoute, request) =>
{
if (internalUiRoute.StartsWith("/") == true && internalUiRoute.StartsWith(request.PathBase) == false)
{
return request.PathBase internalUiRoute;
}
else
{
return internalUiRoute;
}
});
Also see: https://github.com/RicoSuter/NSwag/pull/2196
Run a customized build and select the assembly in NSwagStudio, create an nswag.json and execute it via CLI (nswag run nswag.json
:
For more info, see CommandLine or MSBuild.
app.UseOpenApi(p => p.Path = "/swagger/{documentName}/swagger.yaml");
app.UseSwaggerUi3(p => p.DocumentPath = "/swagger/{documentName}/swagger.yaml");