How do I annotate my ASP.NET WebAPI actions so that the swagger metadata includes the content-types that my resources support?
Specifically, I want the documentation to show that one of my resources can return the 'original' application/json
and application/xml
but also now returns a new format, application/vnd.blah+json
or +xml
.
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 ALOT of info about context.
Extending @VisualBean's answer
On a Controller's API method you could use the below code 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>();
SwaggerReponseContentTypeAttribute.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:
SwaggerReponseContentTypeAttribute.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.
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);
}
}
}
来源:https://stackoverflow.com/questions/34990291/swashbuckle-swagger-how-to-annotate-content-types