Introdução
Antes de colocarmos a mão na massa precisamos entender porque devemos versionar as APIs que colocamos em produção e disponibilizamos para consumo.
Como sabemos, toda API evolui (ou a maioria delas) e estas novas implementações podem ou vão impactar os contratos que disponibilizamos no início. Alterar um contrato pode parecer simples quando poucos clientes estão utilizando nossa API, mas mesmo que seja somente um cliente utilizando nossa API ainda assim é um engano pensar desta forma. Toda e qualquer mudança gerará um impacto, só resta saber se será pequeno ou grande, mas sabemos que gerará.
Quando falamos de contratos REST uma alteração pode ser simples. Você pode manter o contrato atual e simplesmente adicionar uma nova propriedade. Neste caso o impacto será pequeno, o cliente apenas não conseguirá ver e utilizar as informações do novo atributo. Mas se for o caso de tirar uma propriedade ou alterar o nome de uma existente aí sim o impacto será grande. Para o cliente, a nossa API simplesmente deixará de funcionar.
Para resolver este tipo de problema é que utilizamos o versionamento de APIs. Versionando uma API podemos fazer qualquer alteração no contrato e os clientes não serão impactados com isto. O que eles têm implementado continuará funcionando na versão que eles estão utilizando.
Versionando uma API
Primeiro vamos verificar se o .Net Core 3.1 está instalado. Para isto vamos abrir o terminal e digitar o comando abaixo para listar os SDKs instalados:
dotnet --list-sdks

Agora que vimos o .Net Core 3.1 instalado, vamos executar o comando para criar um novo projeto com o nome ApiVersion.
dotnet new webapi -n DotNetCoreApiVersion
Com o projeto criado, vamos abrí-lo no VSCode.

Vamos “buildar” o projeto e executá-lo na sequência:
dotnet build

dotnet run

Vamos utilizar o Postman para fazer a primeira chamada no método GET da API e ver o resultado.
https://localhost:5001/WeatherForecast
Por padrão uma aplicação .Net não vem com o versionamento configurado, para isto precisamos fazer algumas alterações.
Vamos iniciar instalando o package Microsoft.AspNetCore.Mvc.Versioning que nos permitirá fazer o versionamento da nossa API.
No terminal:
dotnet add package Microsoft.AspNetCore.Mvc.Versioning
Ou no Visual Studio:
Install-Package Microsoft.AspNetCore.Mvc.Versioning
Vamos abrir o arquivo Startup.cs e configurar o versionamento da nossa API.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(x =>
{
// Especifica a versão padrão da API
x.DefaultApiVersion = new ApiVersion(1, 0);
// Assume que DefaultApiVersion será a padrão se o cliente não especificar nenhuma
x.AssumeDefaultVersionWhenUnspecified = true;
// Exibe no header a versão da API
x.ReportApiVersions = true;
// Especifica que a versão será utilizada no header
x.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
});
}
Após configurar o Startup.cs vamos executar novamente o GET pelo Postman e ver o resultado no headers da requisição.
Pronto, com isto nossa API já está configurada para ser versionada. Agora vamos ajustar as Controllers para responder a este versionamento.
Importante lembrar que há várias maneiras de se configurar o roteamento da versão em .Net. No nosso caso, vamos utilizar o Header da requisição para especificar qual versão queremos.
Utilizar o Header é a melhor forma de criarmos versionamento sem quebrar versões que já estão em produção. Mas é sempre bom tomar muito cuidado e ter uma boa cobertura de testes para garantir.
Ajustando a Controller
Com o versionamento configurado e pronto para ser usado agora vamos preparar nossa Controller para receber o versionamento pelo Header da requisição.
Aqui no nosso caso vou utilizar a mesma Controller para responder a v1.0 e a v2.0. Também é possível criar diretórios para separar as Controllers, mas como no nosso exemplo só temos um único endpoint então vamos colocar tudo dentro da mesma Controller.
No arquivo WeatherForecastController.cs do projeto criado WebApi criado pelo .Net já tem um endpoint utilizando o método GET. Nós só precisamos decorar este método com o atributo ApiVersion para indicar que este método corresponde à versão 1.0.
[HttpGet]
[ApiVersion("1.0")]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
Ainda na mesma Controller vamos criar um segundo método para atender as requisições que pedirem pela ApiVersion 2.0.
Vamos alterar o atributo Summary concatenando uma string ” :: v2″ como exemplo para identificarmos as requisições feitas.
[HttpGet]
[ApiVersion("2.0")]
public IEnumerable<WeatherForecast> GetV2()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = $"{Summaries[rng.Next(Summaries.Length)]} :: v2"
})
.ToArray();
}
Agora, quando colocamos o atributo x-api-version com o valor 2.0 no Header da requisição o método chamado é o GetV2.

Conclusão
Versionar uma API é essencial para evitar breaking changes nas nossas aplicações. Publicar uma versão em produção que não foi preparada para ser versionada pode acarretar em inúmeros problemas para a empresa e para todos que se relacionam com ela através dos serviços.
Configurar o versionamento de uma API também não garante sucesso na publicação. É de extrema importância ter uma boa cobertura de testes para garantir que refatorações e alterações não quebrem a aplicação.
Os fontes deste artigo podem ser encontrados no meu GitHub.