Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[Oo]bj/
[Bb]in/
.dotnet/
.vs/
.idea*
BenchmarkDotNet.Artifacts*/
Expand Down
7 changes: 7 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"default": true,
"MD013": false,
"MD024": {
"siblings_only": true
}
}
5 changes: 0 additions & 5 deletions ISSUE_TEMPLATE.md

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ for more details.

```csharp
[HttpPost]
public void CreateProduct([FromBody]Product product)
public void CreateProduct([FromBody] Product product)
{
// Implementation goes here
}
Expand Down
104 changes: 62 additions & 42 deletions docs/configure-and-customize-annotations.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
# Configuration & Customization of `Swashbuckle.AspNetCore.Annotations`
# Configuration and Customization of `Swashbuckle.AspNetCore.Annotations`

## Install and Enable Annotations

1. Install the following Nuget package into your ASP.NET Core application.
1. Install the following NuGet package into your ASP.NET Core application.

```
Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations
CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
```terminal
dotnet add package Swashbuckle.AspNetCore.Annotations
```

2. In the `ConfigureServices` method of `Startup.cs`, enable annotations within in the Swagger config block:
2. In your application's startup path, enable annotations within the Swagger configuration callback:

```csharp
services.AddSwaggerGen(options =>
{
//...
// Other setup, then...
options.EnableAnnotations();
});
```

## Enrich Operation Metadata

Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a `SwaggerOperationAttribute`.
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with `[SwaggerOperation]`.

```csharp
[HttpPost]
Expand All @@ -31,43 +30,61 @@ Once annotations have been enabled, you can enrich the generated Operation metad
OperationId = "CreateProduct",
Tags = new[] { "Purchase", "Products" }
)]
public IActionResult Create([FromBody]Product product)
public IActionResult Create([FromBody] Product product)
{
//...
}
```

## Enrich Response Metadata

ASP.NET Core provides the `ProducesResponseTypeAttribute` for listing the different responses that can be returned by an action. These attributes can be combined with XML comments, as described [here](configure-and-customize-swaggergen.md#include-descriptions-from-xml-comments), to include human friendly descriptions with each response in the generated Swagger. If you'd prefer to do all of this with a single attribute, and avoid the use of XML comments, you can use `SwaggerResponseAttribute`s instead:
ASP.NET Core provides the `ProducesResponseTypeAttribute` for listing the different responses that
can be returned by an action. These attributes can be combined with XML comments, as described
[further here](configure-and-customize-swaggergen.md#include-descriptions-from-xml-comments), to
include human-friendly descriptions with each response in the generated document. If you'd prefer
to do all of this with a single attribute, and avoid the use of XML comments, you can use one or more `[SwaggerResponse]` instead:

```csharp
[HttpPost]
[SwaggerResponse(201, "The product was created", typeof(Product))]
[SwaggerResponse(400, "The product data is invalid")]
public IActionResult Create([FromBody]Product product)
public IActionResult Create([FromBody] Product product)
{
//...
}
```

## Enrich Parameter Metadata

You can annotate "path", "query" or "header" bound parameters or properties (i.e. decorated with `[FromRoute]`, `[FromQuery]` or `[FromHeader]`) with a `SwaggerParameterAttribute` to enrich the corresponding `Parameter` metadata that's generated by Swashbuckle:
You can annotate path, query or header-bound parameters or properties (i.e. decorated with `[FromRoute]`, `[FromQuery]`
or `[FromHeader]`) with a `SwaggerParameterAttribute` to enrich the corresponding `Parameter` metadata that's generated by Swashbuckle:

```csharp
[HttpGet]
public IActionResult GetProducts(
[FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)
[FromQuery, SwaggerParameter("Search keywords", Required = true)] string keywords)
{
//...
}
```

## Enrich RequestBody Metadata

You can annotate "body" bound parameters or properties (i.e. decorated with `[FromBody]`) with a `SwaggerRequestBodyAttribute` to enrich the corresponding `RequestBody` metadata that's generated by Swashbuckle:
You can annotate body-bound parameters or properties (i.e. decorated with `[FromBody]`) with `[SwaggerRequestBody]` to enrich
the corresponding `RequestBody` metadata that's generated by Swashbuckle:

```csharp
[HttpPost]
public IActionResult CreateProduct(
[FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)
[FromBody, SwaggerRequestBody("The product payload", Required = true)] Product product)
{
//...
}
```

## Enrich Schema Metadata

You can annotate classes or properties with a `SwaggerSchemaAttribute` to enrich the corresponding `Schema` metadata that's generated by Swashbuckle:
You can annotate classes or properties with `[SwaggerSchema]` to enrich the corresponding `Schema` metadata that's generated by Swashbuckle:

```csharp
[SwaggerSchema(Required = new[] { "Description" })]
Expand All @@ -85,13 +102,20 @@ public class Product
```

> [!NOTE]
> In Swagger / OpenAPI, serialized objects AND contained properties are represented as `Schema` instances, hence why this annotation can be applied to both classes and properties. Also worth noting, "required" properties are specified as an array of property names on the top-level schema as opposed to a flag on each individual property.
> In Swagger/OpenAPI, serialized objects **and** contained properties are represented as `Schema` instances, hence why this annotation can
> be applied to both classes and properties. Also, `required` properties are specified as an array of property names on the top-level schema
> as opposed to a flag on each individual property.

## Apply Schema Filters to Specific Types

The `SwaggerGen` package provides several extension points, including Schema Filters (described [here](configure-and-customize-swaggergen.md#extend-generator-with-operation-schema--document-filter)) for customizing **all** generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the type with a `SwaggerSchemaFilterAttribute`:
The `Swashbuckle.AspNetCore.SwaggerGen` NuGet package provides several extension points, including
[Schema Filters](configure-and-customize-swaggergen.md#extend-generator-with-operation-schema--document-filter) for
customizing **all** generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific
Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the
type with `[SwaggerSchemaFilter]`:

📝 `Product.cs`

```csharp
[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]
public class Product
Expand All @@ -101,6 +125,7 @@ public class Product
```

📝 `ProductSchemaFilter.cs`

```csharp
public class ProductSchemaFilter : ISchemaFilter
{
Expand All @@ -117,7 +142,9 @@ public class ProductSchemaFilter : ISchemaFilter

## Add Tag Metadata

By default, the Swagger generator will tag all operations with the controller name. This tag is then used to drive the operation groupings in the swagger-ui. If you'd like to provide a description for each of these groups, you can do so by adding metadata for each controller name tag via the `SwaggerTagAttribute`:
By default, the Swagger generator will tag all operations with the controller name for MVC applications. This tag is then
used to drive the operation groupings in swagger-ui. If you'd like to provide a description for each of these groups, you
can do so by adding metadata for each controller name tag using `[SwaggerTag]`:

```csharp
[SwaggerTag("Create, read, update and delete Products")]
Expand All @@ -127,14 +154,18 @@ public class ProductsController
}
```

> [!NOTE]
> This will add the above description specifically to the tag named "Products". Therefore, you should avoid using this attribute if you're tagging Operations with something other than controller name - e.g. if you're customizing the tagging behavior with `TagActionsBy`.
> [!NOTE]
> This will add the above description specifically to the tag named `Products`. Therefore, you should avoid using this attribute
> if you're tagging Operations with something other than the controller name - e.g. if you're customizing the tagging behavior with `TagActionsBy`.

## List Known Subtypes for Inheritance and Polymorphism

If you want to use Swashbuckle's [inheritance and/or polymorphism behavior](configure-and-customize-swaggergen.md#inheritance-and-polymorphism), you can use annotations to _explicitly_ indicate the "known" subtypes for a given base type. This will override the default selector function, which selects _all_ subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:
If you want to use Swashbuckle's [inheritance and/or polymorphism behavior](configure-and-customize-swaggergen.md#inheritance-and-polymorphism),
you can use annotations to _explicitly_ indicate the "known" subtypes for a given base type. This will override the default selector function,
which selects _all_ subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:

📝 `Startup.cs`

```csharp
services.AddSwaggerGen(options =>
{
Expand All @@ -143,27 +174,23 @@ services.AddSwaggerGen(options =>
```

📝 `Shape.cs`

```csharp
// .NET 7 or later
[JsonDerivedType(typeof(Rectangle))]
[JsonDerivedType(typeof(Circle))]
public abstract class Shape
{
}

// .NET 6 or earlier
[SwaggerSubType(typeof(Rectangle))]
[SwaggerSubType(typeof(Circle))]
public abstract class Shape
{
}
```

## Enrich Polymorphic Base Classes with Discriminator Metadata

If you're using annotations to _explicitly_ indicate the "known" subtypes for a polymorphic base type, you can combine the `JsonPolymorphicAttribute` with the `JsonDerivedTypeAttribute` to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:
If you're using annotations to _explicitly_ indicate the "known" subtypes for a polymorphic base type, you can combine
`[JsonPolymorphic]` with `[JsonDerivedType]` to provide additional metadata about the "discriminator" property, which will
then be incorporated into the generated schema definition:

📝 `Startup.cs`

```csharp
services.AddSwaggerGen(options =>
{
Expand All @@ -172,8 +199,8 @@ services.AddSwaggerGen(options =>
```

📝 `Shape.cs`

```csharp
// .NET 7 or later
[JsonPolymorphic(TypeDiscriminatorPropertyName = "shapeType")]
[JsonDerivedType(typeof(Rectangle), "rectangle")]
[JsonDerivedType(typeof(Circle), "circle")]
Expand All @@ -184,15 +211,6 @@ public abstract class Shape
// Related issue: https://github.com/dotnet/runtime/issues/72170
}

// .NET 6 or earlier
[SwaggerDiscriminator("shapeType")]
[SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")]
[SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]
public abstract class Shape
{
public ShapeType ShapeType { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum ShapeType
{
Expand All @@ -201,7 +219,9 @@ public enum ShapeType
}
```

This indicates that the corresponding payload will have a "shapeType" property to discriminate between subtypes, and that property will have a value of "rectangle" if the payload represents a `Rectangle` type and a value of "circle" if it represents a `Circle` type. This detail will be described in the generated schema definition as follows:
This indicates that the corresponding payload will have a `"shapeType"` property to discriminate between subtypes, and that property
will have a value of `"rectangle"` if the payload represents a `Rectangle` type and a value of `"circle"` if it represents a `Circle` type.
This detail will be described in the generated schema definition as follows:

```yaml
schema: {
Expand Down
85 changes: 39 additions & 46 deletions docs/configure-and-customize-cli.md
Original file line number Diff line number Diff line change
@@ -1,87 +1,80 @@
# Configuration & Customization of `Swashbuckle.AspNetCore.Cli`
# Configuration and Customization of `Swashbuckle.AspNetCore.Cli`

## Retrieve Swagger Directly from a Startup Assembly
## Retrieve Swagger Directly from a Startup Assembly

Once your application has been setup with Swashbuckle (see [Getting Started](../README.md#getting-started)), you can use the Swashbuckle CLI tool to retrieve Swagger / OpenAPI JSON directly from your application's startup assembly, and write it to file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve it from static file at run-time.
Once your application has been set up with Swashbuckle (see [Getting Started](../README.md#getting-started)), you can
use the Swashbuckle CLI tool to retrieve Swagger/OpenAPI JSON directly from your application's startup assembly, and write
it to a file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve
it from static file at run-time.

It's packaged as a [.NET Tool](https://learn.microsoft.com/dotnet/core/tools/global-tools) that can be installed and used via the dotnet SDK.
It's packaged as a [.NET Tool](https://learn.microsoft.com/dotnet/core/tools/global-tools) that can be installed and used via the .NET SDK.

> [!WARNING]
> The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of the `dotnet` SDK that is compatible with your application. For example, if your app targets `net8.0`, then you should use version 8.0.xxx of the SDK to run the CLI tool. If it targets `net9.0`, then you should use version 9.0.xxx of the SDK and so on.
> [!WARNING]
> The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of the `dotnet` SDK
> that is compatible with your application. For example, if your app targets `net8.0`, then you should use version 8.0.xxx of the SDK
> to run the CLI tool.

### Using the tool with the .NET SDK

1. Install as a [global tool](https://learn.microsoft.com/dotnet/core/tools/global-tools#install-a-global-tool)
#### Install as a Global Tool

```
dotnet tool install -g Swashbuckle.AspNetCore.Cli
```

2. Verify that the tool was installed correctly
To install as a [global tool](https://learn.microsoft.com/dotnet/core/tools/global-tools#install-a-global-tool):

```
swagger tofile --help
```

3. Generate a Swagger/ OpenAPI document from your application's startup assembly

```
swagger tofile --output [output] [startupassembly] [swaggerdoc]
```

Placeholders and their meaning:
* `[output]`: the relative path where the Swagger JSON will be output to
* `[startupassembly]`: the relative path to your application's startup assembly
* `[swaggerdoc]`: the name of the swagger document you want to retrieve, as configured in your startup class
```terminal
dotnet tool install -g Swashbuckle.AspNetCore.Cli
```

### Using the tool with the .NET 6.0 SDK or later
#### Install as a local tool

1. In your project root, create a tool manifest file:
1. In your solution root directory, create a tool manifest file:

```
```terminal
dotnet new tool-manifest
```

2. Install as a [local tool](https://learn.microsoft.com/dotnet/core/tools/global-tools#install-a-local-tool)

```
```terminal
dotnet tool install Swashbuckle.AspNetCore.Cli
```

3. Verify that the tool was installed correctly
### Usage

```
dotnet swagger tofile --help
1. Verify that the tool was installed correctly

```termainal
swagger tofile --help
```

4. Generate a Swagger / OpenAPI document from your application's startup assembly
2. Generate a Swagger/OpenAPI document from your application's startup assembly

```
dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
```terminal
swagger tofile --output [output] [startupassembly] [swaggerdoc]
```

Placeholders and their meaning:
* `[output]`: the relative path where the Swagger JSON will be output to
* `[startupassembly]`: the relative path to your application's startup assembly
* `[swaggerdoc]`: the name of the swagger document you want to retrieve, as configured in your startup class
* `[output]`: the relative path where the Swagger JSON document will be output to;
* `[startupassembly]`: the relative path to your application's startup assembly;
* `[swaggerdoc]`: the name of the Swagger document you want to generate, as configured in your application.

## Use the CLI Tool with a Custom Host Configuration

Out-of-the-box, the tool will execute in the context of a "default" web host. However, in some cases you may want to bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.
By default, the tool will execute in the context of a "default" web host. However, in some cases you may want to
bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this
scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.

That is, if your application contains a class that meets either of the following naming conventions, then that class will be used to provide a host for the CLI tool to run in.
That is, if your application contains a class that meets either of the following naming conventions, then that class
will be used to provide a host for the CLI tool to run in.

- `public class SwaggerHostFactory`, containing a public static method called `CreateHost` with return type `IHost`
- `public class SwaggerWebHostFactory`, containing a public static method called `CreateWebHost` with return type `IWebHost`
* `public class SwaggerHostFactory`, containing a public static method called `CreateHost` with return type `IHost`
* `public class SwaggerWebHostFactory`, containing a public static method called `CreateWebHost` with return type `IWebHost`

For example, the following class could be used to leverage the same host configuration as your application:

```csharp
public class SwaggerHostFactory
{
public static IHost CreateHost()
{
return Program.CreateHostBuilder(new string[0]).Build();
}
=> Program.CreateHostBuilder([]).Build();
}
```
Loading