-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
AspNetCore Middleware
- Package: NSwag.AspNetCore (.NETStandard 1.6+, .NET Standard 2.0, .NET Core and .NET 4.5.1+)
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. Check out this page for more insights about how to customize the generator output. This page is about setting up and configuring the middlewares in ASP.NET Core.
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 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)
{
// SetCompatibilityVersion is only needed for the UseSwagger() methods on ASP.NET Core >= 2.1
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// 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.UseSwagger(); // 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`
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 UseSwagger()
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)
// 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("bearer"));
// new OperationSecurityScopeProcessor("bearer"));
});
You achieve this by telling NSwag to use API key authorization. Inside the API key text box in the Swagger UI you will need to paste in Bearer {your JWT key}
services.AddMvc();
services.AddOpenApiDocument(document =>
{
document.AddSecurity("JWT", Enumerable.Empty<string>(), new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "Authorization",
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Type into the textbox: Bearer {your JWT token}."
});
document.OperationProcessors.Add(
new AspNetCoreOperationSecurityScopeProcessor("JWT"));
// new OperationSecurityScopeProcessor("JWT"));
});
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.