# 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", } } } ```