# Configuration and Customization of `Swashbuckle.AspNetCore.Annotations`
## Install and Enable Annotations
First install the following NuGet package into your ASP.NET Core application.
```terminal
dotnet add package Swashbuckle.AspNetCore.Annotations
```
Next in your application's startup path, enable annotations within the Swagger configuration callback:
```cs
services.AddSwaggerGen(options =>
{
// Other setup, then...
options.EnableAnnotations();
});
```
snippet source | anchor
## Enrich Operation Metadata
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with `[SwaggerOperation]`.
```cs
[HttpPost]
[SwaggerOperation(
Summary = "Creates a new product",
Description = "Requires admin privileges",
OperationId = "CreateProduct",
Tags = ["Purchase", "Products"]
)]
public IActionResult Create([FromBody] Product product)
{
//...
return Ok();
}
```
snippet source | anchor
## 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
[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:
```cs
[HttpPost]
[SwaggerResponse(201, "The product was created", typeof(Product))]
[SwaggerResponse(400, "The product data is invalid")]
public IActionResult Post([FromBody] Product product)
{
//...
return Created();
}
```
snippet source | anchor
## 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.AspNetCore:
```cs
[HttpGet]
public IActionResult GetProducts(
[FromQuery, SwaggerParameter("Search keywords", Required = true)] string keywords)
{
//...
return Ok();
}
```
snippet source | anchor
## Enrich RequestBody Metadata
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.AspNetCore:
```cs
[HttpPost]
public IActionResult SubmitProduct(
[FromBody, SwaggerRequestBody("The product payload", Required = true)] Product product)
{
//...
return Created();
}
```
snippet source | anchor
## Enrich Schema Metadata
You can annotate classes or properties with `[SwaggerSchema]` to enrich the corresponding `Schema` metadata that's generated by Swashbuckle.AspNetCore:
```cs
[SwaggerSchema(Required = ["Description"])]
public class Product
{
[SwaggerSchema("The product identifier", ReadOnly = true)]
public int Id { get; set; }
[SwaggerSchema("The product description")]
public string Description { get; set; } = string.Empty;
[SwaggerSchema("The date it was created", Format = "date")]
public DateTime DateCreated { get; set; }
}
```
snippet source | anchor
> [!NOTE]
> In 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 `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]`:
📝 `Item.cs`
```cs
[SwaggerSchemaFilter(typeof(ItemSchemaFilter))]
public class Item
{
//...
}
```
snippet source | anchor
📝 `ItemSchemaFilter.cs`
```cs
public class ItemSchemaFilter : ISchemaFilter
{
public void Apply(IOpenApiSchema schema, SchemaFilterContext context)
{
if (schema is OpenApiSchema concrete)
{
concrete.Example = new JsonObject
{
["Id"] = 1,
["Description"] = "An awesome item"
};
}
}
}
```
snippet source | anchor
## Add Tag Metadata
By default, the OpenAPI 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](https://github.com/swagger-api/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]`:
```cs
[SwaggerTag("Create, read, update and delete Items")]
public class ItemsController
{
//...
}
```
snippet source | anchor
> [!NOTE]
> This will add the above description specifically to the tag named `Items`. 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:
📝 `Startup.cs`
```cs
services.AddSwaggerGen(options =>
{
options.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});
```
snippet source | anchor
📝 `Shape.cs`
```cs
[JsonDerivedType(typeof(Rectangle))]
[JsonDerivedType(typeof(Circle))]
public abstract class Shape
{
}
```
snippet source | anchor
## 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
`[JsonPolymorphic]` with `[JsonDerivedType]` to provide additional metadata about the "discriminator" property, which will
then be incorporated into the generated schema definition:
📝 `Startup.cs`
```cs
services.AddSwaggerGen(options =>
{
options.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});
```
snippet source | anchor
📝 `ShapeWithDiscriminator.cs`
```cs
[JsonPolymorphic(TypeDiscriminatorPropertyName = "shapeType")]
[JsonDerivedType(typeof(Rectangle), "rectangle")]
[JsonDerivedType(typeof(Circle), "circle")]
public abstract class ShapeWithDiscriminator
{
// Avoid using a JsonPolymorphicAttribute.TypeDiscriminatorPropertyName
// that conflicts with a property in your type hierarchy.
// Related issue: https://github.com/dotnet/runtime/issues/72170
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum ShapeType
{
Circle,
Rectangle
}
```
snippet source | anchor
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: {
oneOf: [
{
$ref: "#/components/schemas/Rectangle"
},
{
$ref: "#/components/schemas/Circle"
},
],
discriminator: {
propertyName: shapeType,
mapping: {
rectangle: "#/components/schemas/Rectangle",
circle: "#/components/schemas/Circle",
}
}
}
```