Como omitir métodos da documentação do Swagger na WebAPI usando o Swashbuckle

135

Eu tenho um aplicativo C # ASP.NET WebAPI com a documentação da API sendo gerada automaticamente usando o Swashbuckle . Quero poder omitir certos métodos da documentação, mas não consigo descobrir como dizer ao Swagger para não incluí-los na saída da interface do usuário do Swagger.

Eu sinto que tem algo a ver com adicionar um filtro de modelo ou esquema, mas não é óbvio o que fazer e a documentação parece fornecer apenas exemplos de como modificar a saída de um método, não removê-la completamente da saída.

Desde já, obrigado.

SteveWilkinson
fonte

Respostas:

337

Você pode adicionar o seguinte atributo a Controladores e ações para excluí-los da documentação gerada: [ApiExplorerSettings(IgnoreApi = true)]

mikesigs
fonte
12
Funcionou muito bem, isso deve ser a resposta
JohnC
4
Existe uma maneira de fazer isso programaticamente? Quero expor uma API em alguns ambientes, mas não em outros, de acordo com uma configuração.
Paul Kienitz
@SyaifulNizamYahya Não tenho certeza. Talvez [JsonIgnore]?
mikesigs
@mikesigs Sim [JsonIgnore] funciona. Infelizmente, proíbe a serialização.
Syaiful Nizam Yahya
4
Documentação Swashbuckle: Omitir arbitrária Operações
spottedmahn
17

Alguém postou a solução no github, então eu vou colá-la aqui. Todos os créditos vão para ele. https://github.com/domaindrivendev/Swashbuckle/issues/153#issuecomment-213342771

Crie primeiro uma classe de atributo

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class HideInDocsAttribute : Attribute
{
}

Em seguida, crie uma classe de filtro de documento

public class HideInDocsFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        foreach (var apiDescription in apiExplorer.ApiDescriptions)
        {
            if (!apiDescription.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<HideInDocsAttribute>().Any() && !apiDescription.ActionDescriptor.GetCustomAttributes<HideInDocsAttribute>().Any()) continue;
            var route = "/" + apiDescription.Route.RouteTemplate.TrimEnd('/');
            swaggerDoc.paths.Remove(route);
        }
    }
}

Em seguida, na classe Swagger Config, adicione esse filtro de documento

public class SwaggerConfig
{
    public static void Register(HttpConfiguration config)
    {
        var thisAssembly = typeof(SwaggerConfig).Assembly;

        config
             .EnableSwagger(c =>
                {
                    ...                       
                    c.DocumentFilter<HideInDocsFilter>();
                    ...
                })
            .EnableSwaggerUi(c =>
                {
                    ...
                });
    }
}

O último passo é adicionar o atributo [HideInDocsAttribute] ao Controller ou Method que você não deseja que o Swashbuckle gere documentação.

Paulo Pozeti
fonte
1
Acho RemoveRoute pode ser o droid que estou procurando.
Paul Kienitz
13

Você pode remover "operações" do documento swagger depois que ele é gerado com um filtro de documento - basta definir o verbo como null (no entanto, pode haver outras maneiras de fazê-lo também)

O exemplo a seguir permite apenas GETverbos - e é retirado desse problema .

class RemoveVerbsFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        foreach (PathItem path in swaggerDoc.paths.Values)
        {
            path.delete = null;
            //path.get = null; // leaving GET in
            path.head = null;
            path.options = null;
            path.patch = null;
            path.post = null;
            path.put = null;
        }
    }
}

e na sua configuração do swagger:

...EnableSwagger(conf => 
{
    // ...

    conf.DocumentFilter<RemoveVerbsFilter>();
});
Dave Transom
fonte
1
Observe: isso não removerá o caminho, mesmo que você remova o comentário path.get = null;- como resultado, esses caminhos ainda serão incluídos no arquivo Swagger, mas apenas sem os detalhes. Talvez seja melhor incluir a ApiExplorerSettingsAttributeresposta como você mencionou na resposta original no GitHub. O uso do ApiExplorerSettings também pode evitar que informações de tipo sejam adicionadas à schemeslista de arquivos do Swagger .
JBert
7

Eu preferiria remover completamente as entradas do dicionário para itens de caminho:

var pathsToRemove = swaggerDoc.Paths
                .Where(pathItem => !pathItem.Key.Contains("api/"))
                .ToList();

foreach (var item in pathsToRemove)
{
    swaggerDoc.Paths.Remove(item.Key);
}

Com essa abordagem, você não obteria itens "vazios" na definição gerada pelo swagger.json.

Denis Biondic
fonte
3

Faça um filtro

public class SwaggerTagFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        foreach(var contextApiDescription in context.ApiDescriptions)
        {
            var actionDescriptor = (ControllerActionDescriptor)contextApiDescription.ActionDescriptor;

    if(!actionDescriptor.ControllerTypeInfo.GetCustomAttributes<SwaggerTagAttribute>().Any() && 
    !actionDescriptor.MethodInfo.GetCustomAttributes<SwaggerTagAttribute>().Any())
            {
                var key = "/" + contextApiDescription.RelativePath.TrimEnd('/');
            swaggerDoc.Paths.Remove(key);
            }
        }
    }
}

Faça um atributo

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class SwaggerTagAttribute : Attribute
{
}

Aplicar em startup.cs

 services.AddSwaggerGen(c => {
            c.SwaggerDoc(1,
                new Info { Title = "API_NAME", Version = "API_VERSION" });
            c.DocumentFilter<SwaggerTagFilter>(); // [SwaggerTag]
        });

Adicione o atributo [SwaggerTag] aos métodos e controladores que você deseja incluir no Swagger JSON

Rowan Stringer
fonte
Doce. Abordagem apropriada e obrigado por compartilhar o sln.
Vedran Mandić
2

Pode ajudar alguém, mas durante o desenvolvimento (depuração) gostamos de expor Controladores e / ou Ações inteiros e depois ocultá-los durante a produção (versão compilada)

#if DEBUG
    [ApiExplorerSettings(IgnoreApi = false)]
#else
    [ApiExplorerSettings(IgnoreApi = true)]
#endif  
Soeren Pedersen
fonte
1

Com base na resposta @spottedmahns . Minha tarefa era vice-versa. Mostre apenas aqueles que são permitidos.

Estruturas: .NetCore 2.1; Swagger: 3.0.0

Atributo adicionado

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ShowInSwaggerAttribute : Attribute
{
}

E implemente IDocumentFilter personalizado

public class ShowInSwaggerFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {

        foreach (var contextApiDescription in context.ApiDescriptions)
        {
            var actionDescriptor = (ControllerActionDescriptor) contextApiDescription.ActionDescriptor;

            if (actionDescriptor.ControllerTypeInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any() ||
                actionDescriptor.MethodInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any())
            {
                continue;
            }
            else
            {
                var key = "/" + contextApiDescription.RelativePath.TrimEnd('/');
                var pathItem = swaggerDoc.Paths[key];
                if(pathItem == null)
                    continue;

                switch (contextApiDescription.HttpMethod.ToUpper())
                {
                    case "GET":
                        pathItem.Get = null;
                        break;
                    case "POST":
                        pathItem.Post = null;
                        break;
                    case "PUT":
                        pathItem.Put = null;
                        break;
                    case "DELETE":
                        pathItem.Delete = null;
                        break;
                }

                if (pathItem.Get == null  // ignore other methods
                    && pathItem.Post == null 
                    && pathItem.Put == null 
                    && pathItem.Delete == null)
                    swaggerDoc.Paths.Remove(key);
            }
        }
    }
}

Código ConfigureServices :

public void ConfigureServices(IServiceCollection services)
{
     // other code

    services.AddSwaggerGen(c =>
    {
        // other configurations
        c.DocumentFilter<ShowInSwaggerFilter>();
    });
}
aleha
fonte
Obrigado Aleha. Essa abordagem realmente funciona bem para SwashBuckle.OData onde ApiExplorerSettingsAttribute não funciona.
Prasad Korhale 17/06/19
1

adicione uma linha SwaggerConfig c.DocumentFilter ();

public class HideInDocsFilter : IDocumentFilter
    {
        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
        { 
var pathsToRemove = swaggerDoc.Paths
                .Where(pathItem => !pathItem.Key.Contains("api/"))
                .ToList();

foreach (var item in pathsToRemove)
{
    swaggerDoc.Paths.Remove(item.Key);
}
    }
}
Vikramraj
fonte
0

Adicione isso aos seus métodos que você deseja omitir

[ApiExplorerSettings(IgnoreApi=true)]
Mridusmita Deka
fonte