Swashbuckle Swagger - How to annotate content types?
What you need to do is this; Swagger spec: you need to add your response-type to the list of response-types for that operation:
"produces": [
"application/json",
"text/json"
],
This can be done with an OperationFilter.
Pseudo Code incoming!!!
public class CustomResponseType : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.operationId == "myCustomName")
{
operation.produces.Add("application/vnd.blah+json");
}
}
}
the OperationId can be set through the [SwaggerOperation("myCustomName")]
annotation.
Then apply the operationsFilter in the swaggerConfig.cs:
c.OperationFilter<CustomResponseType>();
Note:
instead of operation.operationId == "myCustomName"
you could do it for a particular route or anything else basically. ApiDescription gives a LOT of info about context.
Following on OzBob's answer. Since Swashbuckle 4.0.x, you may need to update the operation filter code slightly:
ResponseContentTypeOperationFilter.cs
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Linq;
public class ResponseContentTypeOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (!context.ApiDescription.TryGetMethodInfo(out var methodInfo))
{
return;
}
var requestAttributes = methodInfo.GetCustomAttributes(true).OfType<SwaggerResponseContentTypeAttribute>().FirstOrDefault();
if (requestAttributes != null)
{
if (requestAttributes.Exclusive)
operation.Produces.Clear();
operation.Produces.Add(requestAttributes.ResponseType);
}
}
}
Extending @VisualBean's answer.
On a Controller's API method, you could use the code below to set an Attribute like:
[SwaggerResponseContentType(responseType:"application/pdf", Exclusive=true)]
public HttpResponseMessage GetAuthorityForm(string id)
{
....
Note: 'Exclusive=true' will remove all other content types, otherwise using the new Attribute will add a new Response Content Type in the Swagger UI drop down. It will NOT modify your Controller or API, just the documentation.
SwaggerConfig.cs
GlobalConfiguration.Configuration
.EnableSwagger(c =>
// Set filter to apply Custom Content Types to operations
//
c.OperationFilter<ResponseContentTypeOperationFilter>();
SwaggerResponseContentTypeAttribute.cs
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class SwaggerResponseContentTypeAttribute : Attribute
{
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
/// <param name="responseType"></param>
public SwaggerResponseContentTypeAttribute(string responseType)
{
ResponseType = responseType;
}
/// <summary>
/// Response Content Type
/// </summary>
public string ResponseType { get; private set; }
/// <summary>
/// Remove all other Response Content Types
/// </summary>
public bool Exclusive { get; set; }
}
ResponseContentTypeOperationFilter.cs
public class ResponseContentTypeOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var requestAttributes = apiDescription.GetControllerAndActionAttributes<SwaggerResponseContentTypeAttribute>().FirstOrDefault();
if (requestAttributes != null)
{
if (requestAttributes.Exclusive)
operation.produces.Clear();
operation.produces.Add(requestAttributes.ResponseType);
}
}
}
@OzBob's answer assumes you only want to add a single attribute to a method. If you want to add and document more than one content types for the same method, you can use the following:
SwaggerResponseContentTypeAttribute.cs
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerResponseContentTypeAttribute : Attribute
{
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
/// <param name="responseType"></param>
public SwaggerResponseContentTypeAttribute(string responseType)
{
ResponseType = responseType;
}
/// <summary>
/// Response Content Type
/// </summary>
public string ResponseType { get; private set; }
/// <summary>
/// Remove all other Response Content Types
/// </summary>
public bool Exclusive { get; set; }
}
ResponseContentTypeOperationFilter.cs
public class ResponseContentTypeOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var requestAttributes = apiDescription.GetControllerAndActionAttributes<SwaggerResponseContentTypeAttribute>();
foreach (var requestAttribute in requestAttributes)
{
if (requestAttribute.Exclusive)
{
operation.produces.Clear();
}
operation.produces.Add(requestAttribute.ResponseType);
}
}
}
Note that when you have multiple attributes on the same method and you want to replace the existing content types, you should set Exclusive = true
on the first attribute only. Otherwise, you won't get all the attributes into the documentation.