Swashbuckle Swagger - How to annotate content types?

前端 未结 4 811
南方客
南方客 2020-12-16 12:02

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

相关标签:
4条回答
  • 2020-12-16 12:46

    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 12:53

    @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.

    0 讨论(0)
  • 2020-12-16 12:55

    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.

    0 讨论(0)
  • 2020-12-16 13:01

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题