Skip to content

Commit 91b05c6

Browse files
authored
[Docs] Split README (#3405)
Split up the README into multiple additional documentation files. Contributes to #3365.
1 parent 6c655b6 commit 91b05c6

7 files changed

+1589
-1602
lines changed

README.md

Lines changed: 54 additions & 1602 deletions
Large diffs are not rendered by default.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Configuration & Customization of `Swashbuckle.AspNetCore.Annotations`
2+
3+
## Install and Enable Annotations
4+
5+
1. Install the following Nuget package into your ASP.NET Core application.
6+
7+
```
8+
Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations
9+
CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
10+
```
11+
12+
2. In the `ConfigureServices` method of `Startup.cs`, enable annotations within in the Swagger config block:
13+
14+
```csharp
15+
services.AddSwaggerGen(c =>
16+
{
17+
...
18+
19+
c.EnableAnnotations();
20+
});
21+
```
22+
23+
## Enrich Operation Metadata
24+
25+
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a `SwaggerOperationAttribute`.
26+
27+
```csharp
28+
[HttpPost]
29+
30+
[SwaggerOperation(
31+
Summary = "Creates a new product",
32+
Description = "Requires admin privileges",
33+
OperationId = "CreateProduct",
34+
Tags = new[] { "Purchase", "Products" }
35+
)]
36+
public IActionResult Create([FromBody]Product product)
37+
```
38+
39+
## Enrich Response Metadata
40+
41+
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 [above](#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:
42+
43+
```csharp
44+
[HttpPost]
45+
[SwaggerResponse(201, "The product was created", typeof(Product))]
46+
[SwaggerResponse(400, "The product data is invalid")]
47+
public IActionResult Create([FromBody]Product product)
48+
```
49+
50+
## Enrich Parameter Metadata
51+
52+
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:
53+
54+
```csharp
55+
[HttpGet]
56+
public IActionResult GetProducts(
57+
[FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)
58+
```
59+
60+
## Enrich RequestBody Metadata
61+
62+
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:
63+
64+
```csharp
65+
[HttpPost]
66+
public IActionResult CreateProduct(
67+
[FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)
68+
```
69+
70+
## Enrich Schema Metadata
71+
72+
You can annotate classes or properties with a `SwaggerSchemaAttribute` to enrich the corresponding `Schema` metadata that's generated by Swashbuckle:
73+
74+
```csharp
75+
[SwaggerSchema(Required = new[] { "Description" })]
76+
public class Product
77+
{
78+
[SwaggerSchema("The product identifier", ReadOnly = true)]
79+
public int Id { get; set; }
80+
81+
[SwaggerSchema("The product description")]
82+
public string Description { get; set; }
83+
84+
[SwaggerSchema("The date it was created", Format = "date")]
85+
public DateTime DateCreated { get; set; }
86+
}
87+
```
88+
89+
_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._
90+
91+
## Apply Schema Filters to Specific Types
92+
93+
The `SwaggerGen` package provides several extension points, including Schema Filters ([described here](#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`:
94+
95+
```csharp
96+
// Product.cs
97+
[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]
98+
public class Product
99+
{
100+
...
101+
}
102+
103+
// ProductSchemaFilter.cs
104+
public class ProductSchemaFilter : ISchemaFilter
105+
{
106+
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
107+
{
108+
schema.Example = new OpenApiObject
109+
{
110+
[ "Id" ] = new OpenApiInteger(1),
111+
[ "Description" ] = new OpenApiString("An awesome product")
112+
};
113+
}
114+
}
115+
```
116+
117+
## Add Tag Metadata
118+
119+
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`:
120+
121+
```csharp
122+
[SwaggerTag("Create, read, update and delete Products")]
123+
public class ProductsController
124+
{
125+
...
126+
}
127+
```
128+
129+
_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`._
130+
131+
## List Known Subtypes for Inheritance and Polymorphism
132+
133+
If you want to use Swashbuckle's [inheritance and/or polymorphism behavior](#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:
134+
135+
```csharp
136+
// Startup.cs
137+
services.AddSwaggerGen(c =>
138+
{
139+
c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
140+
});
141+
142+
// Shape.cs
143+
144+
// .NET 7 or later
145+
[JsonDerivedType(typeof(Rectangle))]
146+
[JsonDerivedType(typeof(Circle))]
147+
public abstract class Shape
148+
{
149+
}
150+
151+
// .NET 6 or earlier
152+
[SwaggerSubType(typeof(Rectangle))]
153+
[SwaggerSubType(typeof(Circle))]
154+
public abstract class Shape
155+
{
156+
}
157+
```
158+
159+
## Enrich Polymorphic Base Classes with Discriminator Metadata
160+
161+
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:
162+
163+
164+
```csharp
165+
// Startup.cs
166+
services.AddSwaggerGen(c =>
167+
{
168+
c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
169+
});
170+
171+
// Shape.cs
172+
173+
// .NET 7 or later
174+
[JsonPolymorphic(TypeDiscriminatorPropertyName = "shapeType")]
175+
[JsonDerivedType(typeof(Rectangle), "rectangle")]
176+
[JsonDerivedType(typeof(Circle), "circle")]
177+
public abstract class Shape
178+
{
179+
// Avoid using a JsonPolymorphicAttribute.TypeDiscriminatorPropertyName
180+
// that conflicts with a property in your type hierarchy.
181+
// Related issue: https://github.com/dotnet/runtime/issues/72170
182+
}
183+
184+
// .NET 6 or earlier
185+
[SwaggerDiscriminator("shapeType")]
186+
[SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")]
187+
[SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]
188+
public abstract class Shape
189+
{
190+
public ShapeType ShapeType { get; set; }
191+
}
192+
193+
[JsonConverter(typeof(JsonStringEnumConverter))]
194+
public enum ShapeType
195+
{
196+
Circle,
197+
Rectangle
198+
}
199+
```
200+
201+
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:
202+
203+
```
204+
schema: {
205+
oneOf: [
206+
{
207+
$ref: "#/components/schemas/Rectangle"
208+
},
209+
{
210+
$ref: "#/components/schemas/Circle"
211+
},
212+
],
213+
discriminator: {
214+
propertyName: shapeType,
215+
mapping: {
216+
rectangle: "#/components/schemas/Rectangle",
217+
circle: "#/components/schemas/Circle",
218+
}
219+
}
220+
}
221+
```

docs/configure-and-customize-cli.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Configuration & Customization of `Swashbuckle.AspNetCore.Cli`
2+
3+
## Retrieve Swagger Directly from a Startup Assembly
4+
5+
Once your application has been setup with Swashbuckle (see [Getting Started](#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.
6+
7+
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.
8+
9+
> :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.
10+
11+
### Using the tool with the .NET SDK
12+
13+
1. Install as a [global tool](https://learn.microsoft.com/dotnet/core/tools/global-tools#install-a-global-tool)
14+
15+
```
16+
dotnet tool install -g Swashbuckle.AspNetCore.Cli
17+
```
18+
19+
2. Verify that the tool was installed correctly
20+
21+
```
22+
swagger tofile --help
23+
```
24+
25+
3. Generate a Swagger/ OpenAPI document from your application's startup assembly
26+
27+
```
28+
swagger tofile --output [output] [startupassembly] [swaggerdoc]
29+
```
30+
31+
Where ...
32+
* [output] is the relative path where the Swagger JSON will be output to
33+
* [startupassembly] is the relative path to your application's startup assembly
34+
* [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
35+
36+
### Using the tool with the .NET 6.0 SDK or later
37+
38+
1. In your project root, create a tool manifest file:
39+
40+
```
41+
dotnet new tool-manifest
42+
```
43+
44+
2. Install as a [local tool](https://learn.microsoft.com/dotnet/core/tools/global-tools#install-a-local-tool)
45+
46+
```
47+
dotnet tool install Swashbuckle.AspNetCore.Cli
48+
```
49+
50+
3. Verify that the tool was installed correctly
51+
52+
```
53+
dotnet swagger tofile --help
54+
```
55+
56+
4. Generate a Swagger / OpenAPI document from your application's startup assembly
57+
58+
```
59+
dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
60+
```
61+
62+
Where ...
63+
* [output] is the relative path where the Swagger JSON will be output to
64+
* [startupassembly] is the relative path to your application's startup assembly
65+
* [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
66+
67+
## Use the CLI Tool with a Custom Host Configuration
68+
69+
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.
70+
71+
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.
72+
73+
- `public class SwaggerHostFactory`, containing a public static method called `CreateHost` with return type `IHost`
74+
- `public class SwaggerWebHostFactory`, containing a public static method called `CreateWebHost` with return type `IWebHost`
75+
76+
For example, the following class could be used to leverage the same host configuration as your application:
77+
78+
```csharp
79+
public class SwaggerHostFactory
80+
{
81+
public static IHost CreateHost()
82+
{
83+
return Program.CreateHostBuilder(new string[0]).Build();
84+
}
85+
}
86+
```

docs/configure-and-customize-redoc.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Configuration & Customization of `Swashbuckle.AspNetCore.ReDoc`
2+
3+
## Change Relative Path to the UI
4+
5+
By default, the Redoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the Redoc middleware:
6+
7+
```csharp
8+
app.UseReDoc(c =>
9+
{
10+
c.RoutePrefix = "docs"
11+
...
12+
}
13+
```
14+
15+
## Change Document Title
16+
17+
By default, the Redoc UI will have a generic document title. You can alter this when enabling the Redoc middleware:
18+
19+
```csharp
20+
app.UseReDoc(c =>
21+
{
22+
c.DocumentTitle = "My API Docs";
23+
...
24+
}
25+
```
26+
27+
## Apply Redoc Parameters
28+
29+
Redoc ships with its own set of configuration parameters, all described here https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object. In Swashbuckle, most of these are surfaced through the Redoc middleware options:
30+
31+
```csharp
32+
app.UseReDoc(c =>
33+
{
34+
c.SpecUrl("/v1/swagger.json");
35+
c.EnableUntrustedSpec();
36+
c.ScrollYOffset(10);
37+
c.HideHostname();
38+
c.HideDownloadButton();
39+
c.ExpandResponses("200,201");
40+
c.RequiredPropsFirst();
41+
c.NoAutoAuth();
42+
c.PathInMiddlePanel();
43+
c.HideLoading();
44+
c.NativeScrollbars();
45+
c.DisableSearch();
46+
c.OnlyRequiredInSamples();
47+
c.SortPropsAlphabetically();
48+
});
49+
```
50+
51+
_Using `c.SpecUrl("/v1/swagger.json")` multiple times within the same `UseReDoc(...)` will not add multiple urls._
52+
53+
## Inject Custom CSS
54+
55+
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your `wwwroot` folder and specifying the relative paths in the middleware options:
56+
57+
```csharp
58+
app.UseReDoc(c =>
59+
{
60+
...
61+
c.InjectStylesheet("/redoc/custom.css");
62+
}
63+
```
64+
65+
It is also possible to modify the theme by using the `AdditionalItems` property, see https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object for more information.
66+
67+
```csharp
68+
app.UseReDoc(c =>
69+
{
70+
...
71+
c.ConfigObject.AdditionalItems = ...
72+
}
73+
```
74+
75+
## Customize index.html
76+
77+
To customize the UI beyond the basic options listed above, you can provide your own version of the Redoc index.html page:
78+
79+
```csharp
80+
app.UseReDoc(c =>
81+
{
82+
c.IndexStream = () => GetType().Assembly
83+
.GetManifestResourceStream("CustomIndex.ReDoc.index.html"); // requires file to be added as an embedded resource
84+
});
85+
```
86+
87+
_To get started, you should base your custom index.html on the [default version](src/Swashbuckle.AspNetCore.ReDoc/index.html)_

0 commit comments

Comments
 (0)