web-dev-qa-db-fra.com

Swashbuckle Swagger - Comment annoter les types de contenu?

Comment annoter mes actions ASP.NET WebAPI afin que les métadonnées swagger incluent les types de contenu pris en charge par mes ressources?

Plus précisément, je souhaite que la documentation indique qu'une de mes ressources peut renvoyer les application/json et application/xml 'originaux', mais renvoie également un nouveau format, application/vnd.blah+json ou +xml.

13
Luke Puplett

Ce que vous devez faire est le suivant: Spécification Swagger: Vous devez ajouter votre type de réponse à la liste des types de réponses pour cette opération.

"produces": [
            "application/json",
            "text/json"
            ],

Cela peut être fait avec un OperationFilter

Pseudo Code entrant !!!

public class CustomResponseType : IOperationFilter
{        
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {            
            if (operation.operationId == "myCustomName")
            {
                operation.produces.Add("application/vnd.blah+json");
            }            
    }      
}

operationId peut être défini via l'annotation [SwaggerOperation("myCustomName")].

Appliquez ensuite le fichier operationsFilter dans le fichier swaggerConfig.cs.

c.OperationFilter<CustomResponseType>();

Remarque: Au lieu de operation.operationId == "myCustomName"vous pouvez le faire pour un itinéraire particulier ou pour n’importe quoi d’autre. ApiDescription donne beaucoup d'informations sur le contexte.

8
VisualBean

Étendre la réponse de @ VisualBean 

Sur la méthode de l'API d'un contrôleur, vous pouvez utiliser le code ci-dessous pour définir un attribut tel que:

[SwaggerResponseContentType(responseType:"application/pdf", Exclusive=true)]
public HttpResponseMessage GetAuthorityForm(string id)
{
....

Remarque: "Exclusive = true" supprimera tous les autres types de contenu. Sinon, le nouvel attribut ajoutera un nouveau type de contenu de réponse dans la liste déroulante des interfaces utilisateur Swagger. Cela ne modifiera PAS votre contrôleur ou votre API uniquement la 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);
        }
    }
}
36
OzBob

La réponse de @ OzBob suppose que vous voulez uniquement ajouter un seul attribut à une méthode. Si vous souhaitez ajouter et documenter plusieurs types de contenu pour la même méthode, vous pouvez utiliser les éléments suivants:

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);
        }
    }
}

Notez que lorsque vous avez plusieurs attributs sur la même méthode et que vous souhaitez remplacer les types de contenu existants, vous devez définir Exclusive = true sur le premier attribut uniquement. Sinon, vous n'obtiendrez pas tous les attributs dans la documentation.

5
bjorgvin

Suite à la réponse de OzBob. Depuis Swashbuckle 4.0.x, vous devrez peut-être légèrement mettre à jour le code de filtrage de l'opération:

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);
        }
    }
}
2
Grubl3r