Em sistemas que utilizam APIs RESTful, uma das maiores preocupações é garantir que a evolução do software não quebre a compatibilidade com clientes que já estão em produção. Quando alteramos uma API (adicionando novas funcionalidades, modificando comportamentos ou corrigindo bugs), a introdução de mudanças pode afetar os clientes que ainda utilizam versões anteriores. Por isso, versionar uma API é fundamental para garantir a estabilidade e a continuidade dos serviços.

Neste artigo, vamos explorar como implementar o versionamento de APIs no ASP.NET Core, demonstrando as diferentes abordagens para garantir a compatibilidade entre versões e a evolução controlada da API.

Por que versionar uma API?

O versionamento de uma API é uma prática essencial para o desenvolvimento de software escalável e sustentável. Ele oferece várias vantagens:

Compatibilidade com clientes existentes: com o versionamento, você pode garantir que os clientes que já estão utilizando uma versão anterior da API não serão impactados por mudanças incompatíveis.

Evolução controlada: à medida que novos recursos são adicionados ou melhorias são feitas na API, o versionamento permite que novas funcionalidades sejam introduzidas sem quebrar as versões anteriores.

Estabilidade: o versionamento assegura que as versões antigas da API permaneçam estáveis e funcionais, enquanto novas versões podem ser experimentadas e ajustadas sem causar interrupções.

Documentação e manutenção: as versões ajudam a documentar as mudanças feitas ao longo do tempo, facilitando a manutenção e a integração com novos desenvolvedores ou equipes.

Formas de versionar APIs ASP.NET Core

Existem várias maneiras de versionar uma API no ASP.NET Core. A escolha do método adequado depende do contexto e das necessidades do seu projeto. Abaixo, exploraremos as principais abordagens:

Implementando o versionamento

Para implementar o controle de versão de API, vamos precisar do seguinte pacote:

				
					.NET CLI
dotnet add package Asp.Versioning.Mvc.ApiExplorer

Package Manager
Install-Package Asp.Versioning.Mvc.ApiExplorer

				
			

Esse pacote oferece as funcionalidades necessárias para o versionamento de API, permitindo que você documente suas versões.

Agora, vamos criar dois controladores: um para a versão 1.0 e outro para a versão 2.0 da nossa API. Esses controladores terão a mesma rota, mas com versões diferentes.

				
					using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

namespace APITest.Controllers.v1;

[ApiController]
[Route("api/v{version:apiVersion}/products")]
[ApiVersion("1.0")]
public class ProdutosV1Controller : ControllerBase
{
    [HttpGet]
    public IActionResult GetProdutosV1()
    {
        return Ok(new { Message = "Versão 1.0 - Produtos" });
    }
}

				
			

Aqui, usamos a anotação “[ApiVersion(“1.0”)]” para definir que este controlador é da versão “1.0”. A rota da API inclui a versão da API, o que permite que a versão seja especificada diretamente na URL.

Em seguida, vamos criar o controlador para a versão “2.0” da nossa API. O código será muito semelhante ao do controlador da versão “1.0”, mas com algumas melhorias ou novos recursos.

				
					using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

namespace APITest.Controllers.v2;

[ApiController]
[Route("api/v{version:apiVersion}/products")]
[ApiVersion("2.0")]
public class ProductsV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult GetProductsV2()
    {
      return Ok(new { Message = "Versão 2.0 - Produtos com novas funcionalidades" });
    }
}

				
			

Você pode separá-las em pastas para organizar melhor:

Agora que temos os controladores prontos, precisamos configurar o nosso “Program.cs”

				
					builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning()
    .AddMvc()
    .AddApiExplorer(setup =>
    {
        setup.GroupNameFormat = "'v'VVV";
        setup.SubstituteApiVersionInUrl = true;
    });

				
			

No código acima, nós adicionamos o serviço API Explorer à coleção de serviços da aplicação. Ele permite que a documentação da API seja gerada dinamicamente, incluindo detalhes sobre os métodos HTTP (GET, POST, etc.), os parâmetros e os tipos de resposta.

Em seguida, adicionamos o “AddApiVersioning” que adiciona o serviço de versionamento de API à coleção de serviços. Ele vai nos permitir versionar a nossa API.

Também adicionamos o “AddMvc” que adiciona o suporte ao MVC (Model-View-Controller) para a aplicação. Embora o nome sugira que ele seja usado para aplicações com interface de usuário, em um contexto de API, ele basicamente habilita a funcionalidade de controller e manipulação de dados, como roteamento de requisições HTTP para métodos específicos em seus controladores.

Por fim, o “AddApiExplorer” configura a exploração da API para incluir mais detalhes sobre as versões e os endpoints. O “GroupNameFormat ” define como o nome do grupo de versões da API será formatado. No caso, “’v’VVV” significa que os nomes dos grupos serão algo como v1, v2, v3, etc. Ou seja, ele vai gerar uma versão formatada com “v” seguido pela versão numérica da API. 

O “SubstituteApiVersionInUrl” garante que o número da versão da API será substituído na URL. Ao configurar isso para true, ele permite que as rotas da API incluam a versão diretamente na URL.

Agora colocando a aplicação para executar e acessando os endpoints de cada versão, teremos respostas diferentes.

Dessa forma, podemos acessar os endpoints diretamente por meio de suas URLs, com a versão da API incluída na rota. No entanto, se estivermos utilizando o Swagger, não será possível selecionar qual versão queremos utilizar, pois ele não foi configurado para lidar com versões de API. Para permitir a seleção da versão no Swagger, é necessário configurá-lo adequadamente. Siga os passos abaixo para realizar essa configuração.

Primeiro, vamos criar uma nova pasta em nosso projeto chamada “SwaggerConfig” (ou qualquer nome que preferir) e, dentro dessa pasta, vamos adicionar um novo arquivo de configuração do Swagger. Vamos chamá-lo de “ConfigureSwaggerGenOptions”.

Dentro deste arquivo, vamos criar uma classe chamada “ConfigureSwaggerGenOptions”, que irá implementar a interface “IConfigureOptions<SwaggerGenOptions>”. Essa interface é responsável por configurar as opções do Swagger, permitindo personalizar como a documentação da API será gerada.

				
					public class ConfigureSwaggerGenOptions : IConfigureOptions<SwaggerGenOptions>
    {
        private readonly IApiVersionDescriptionProvider _apiVersionDescriptionProvider;

        public ConfigureSwaggerGenOptions(IApiVersionDescriptionProvider apiVersionDescriptionProvider)
        {
            _apiVersionDescriptionProvider = apiVersionDescriptionProvider;
        }

				
			

No código acima estamos injetando a interface “IApiVersionDescriptionProvider” que fornece informações sobre as versões da API disponíveis. O Swagger usa essas informações para gerar a documentação para cada versão.

				
					public void Configure(SwaggerGenOptions options)
{
    foreach (var description in _apiVersionDescriptionProvider.ApiVersionDescriptions)
    {
        options.SwaggerDoc(description.GroupName, CreateOpenApiInfo(description));
    }
}

				
			

Em seguida, implementamos a classe “Configure” da interface que para cada versão da API fornecida pelo “IApiVersionDescriptionProvider”, estamos chamando o método “SwaggerDoc” do Swagger, que adiciona uma documentação específica para cada versão. O método “CreateOpenApiInfo” (que será implementado a seguir) cria as informações detalhadas para cada versão da API, como o título e a versão da API.

				
					private static OpenApiInfo CreateOpenApiInfo(ApiVersionDescription description)
{
    var info = new OpenApiInfo()
    {
        Title = "Versionamento API", 
        Version = description.ApiVersion.ToString()
    };

    if (description.IsDeprecated)
    {
        info.Description += " (deprecated)";
    }

    return info;
}

				
			

Esse método cria as informações detalhadas para o Swagger, como o título e a versão da API. Se a versão estiver descontinuada, ela é marcada como “deprecated”.

Agora, vamos configurar o “Program.cs” para garantir que o Swagger funcione corretamente com o versionamento da API. Precisamos registrar as configurações que definimos e habilitar a interface do Swagger UI, permitindo que o usuário visualize a documentação das diferentes versões da API

				
					builder.Services.ConfigureOptions<ConfigureSwaggerGenOptions>();
				
			

O código acima, garante que as opções de configuração do Swagger, definidas em “ConfigureSwaggerGenOptions”, sejam aplicadas:

				
					app.UseSwaggerUI(options =>
{
    var version = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
    foreach (var description in version.ApiVersionDescriptions)
    {
        options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", $"Web Api - {description.GroupName.ToUpper()}");
    }
});

				
			
O código acima, modifica o “app.UseSwaggerUI()” para exibir a documentação de cada versão da API. Nele recuperamos as versões da API registradas e geramos um endpoint Swagger para cada versão, permitindo que o Swagger UI mostre a documentação e ofereça testes interativos para cada versão.

Acelere a sua carreira conosco!

Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET StartClique aqui

Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET ExpertClique aqui

Conclusão

Neste artigo, mostramos como implementar o versionamento de API no ASP.NET Core com a biblioteca “Asp.Versioning”, configurando o Swagger para gerar documentação interativa para diferentes versões da API. Essa abordagem permite que a API evolua sem quebrar a compatibilidade com versões anteriores, facilitando a manutenção e proporcionando uma experiência mais organizada e acessível para desenvolvedores. Com isso, você agora pode versionar e testar sua API de maneira eficiente usando o Swagger UI.