Domine o Controle de Versão em APIs .Net

Olá, Devs! Vamos entender controle de versão no .Net?

Em um mundo dominado por sistemas interconectados e aplicações que constantemente comunicam entre si, a gestão e evolução das interfaces de programação de aplicações (APIs) é crucial, especialmente quando se refere à API do .Net. Em ambientes de desenvolvimento modernos, o controle de versão desempenha um papel essencial, garantindo que as modificações feitas na API não comprometam as aplicações existentes que a utilizam.

 

1. Importância do controle de versão

Os desenvolvedores geralmente evoluem uma API primeiramente porque querem introduzir novas funcionalidades ou por outro lado, melhorar sua performance. No entanto, se eles não gerenciarem as alterações corretamente, incompatibilidades podem surgir e consequentemente prejudicar sistemas em produção. Dessa forma, no contexto da API do .Net, precisamos de um mecanismo eficiente de controle de versão.

2. Métodos tradicionais e seus desafios

Tradicionalmente, desenvolvedores implementam o controle de versão em APIs através do versionamento por URL ou usando cabeçalhos HTTP. No primeiro método, eles especificam a versão diretamente na URL da API, como em: api/v1/recurso. No segundo, eles indicam a versão em um cabeçalho HTTP, como Accept-Version: v1.0.

Porém, desenvolvedores enfrentam desafios frequentemente. Quando eles incorporam a versão da API à URL, mudanças na estrutura da API podem resultar em URLs desorganizadas. Já o uso de cabeçalhos pode confundir desenvolvedores menos experientes.

3. Soluções que o .Net oferece

Na API do .Net, os desenvolvedores encontram mecanismos refinados para controlar as versões. O .Net introduziu uma biblioteca específica, a Microsoft.AspNetCore.Mvc.Versioning, para simplificar esse processo.

Ao usar essa biblioteca, os desenvolvedores podem especificar a versão da API através de um parâmetro de consulta, um cabeçalho personalizado ou diretamente no caminho da URL. Por exemplo, eles podem fazer uma solicitação assim: api/recurso?api-version=2.0.

Essa abordagem oferece vantagens notáveis. Primeiramente, ela estabelece um padrão uniforme, tornando o versionamento transparente e consistente. Além disso, com essa biblioteca, diferentes versões da API podem coexistir no mesmo endereço, facilitando uma transição suave entre elas.

4. Vamos ver um exemplo?

Considere o desenvolvimento de uma API que gerencia informações de estudantes. Na primeira versão, tem-se um método para obter o nome do estudante. Com o tempo, surge a necessidade de expandir essa funcionalidade, adicionando um método para obter a média de notas do estudante.

Sem o controle adequado de versão, essa nova funcionalidade poderia comprometer sistemas que dependem da versão anterior da API. No entanto, com o uso da biblioteca Microsoft.AspNetCore.Mvc.Versioning, é possível manter ambas as versões funcionando simultaneamente.

Como faço?

Primeiramente, você terá que adicionar a biblioteca Microsoft.AspNetCore.Mvc.Versioning ao projeto. Isso pode ser feito via NuGet Package Manager ou via linha de comando:

Instalação do pacote

Depois de adicionada, configure o serviço:

Configuração do serviço

Aqui, configuramos a API para ter uma versão padrão de 1.0. Se nenhuma versão for especificada na solicitação, ela assumirá 1.0 como padrão. A opção ReportApiVersions informará aos clientes quais versões estão disponíveis.

Crie a Controller de estudantes

  • Para versão 1 da API:

Versão 1.0

No exemplo acima, uma requisição GET para /api/students/1/name?api-version=1.0 retornará “Estudante 1: João Silva”.

  • Para versão 2 da API:

Versão 2.0

Agora, uma requisição GET para /api/students/1/averageGrade?api-version=2.0 retornará “Estudante 1: Média 8.5”.

 

Posso fazer de outras formas?

Sim, você pode decorar a Controller com várias versões de API usando a anotação  [ApiVersion] várias vezes. Isso significa que a controller (ou a ação, dependendo de onde você coloca a anotação) pode atender a múltiplas versões da API.

Se você quiser que o método GetStudentName esteja disponível em ambas as versões “1.0” e “2.0”, você pode fazer o seguinte:

Versões 1.0 e 2.0

Neste exemplo, o método GetStudentName estará disponível para ambas api-version=1.0 e api-version=2.0 .

Se você quiser ser ainda mais granular e especificar versões em nível de ação (em vez da controller), você pode fazer isso também. Por exemplo, você pode ter um método na controller que é específico para uma versão e outro método para outra versão:

Versão para ação

Neste cenário, o comportamento de GetStudentName pode variar dependendo da versão da API solicitada pelo cliente.


Existe também, a anotação [MapToApiVersion] que é usada para indicar explicitamente que uma ação específica em uma controller deve responder apenas a uma determinada versão da API, mesmo se o controlador em si estiver decorado para atender a várias versões.

Vamos ver como isso se aplica no contexto do nosso exemplo anterior:

MapToApiVersion

Neste exemplo, a ação GetVersionSpecificInfo só responderá às solicitações que especificam api-version=2.0,  graças à anotação [MapToApiVersion(“2.0”)]. No  entanto, o método GetStudentName ainda está disponível para ambas as versões “1.0” e “2.0”, já que ele não possui uma anotação MapToApiVersion e a controller em si suporta ambas as versões.

A anotação [MapToApiVersion] fornece uma granularidade adicional, permitindo que os desenvolvedores definam comportamentos específicos para versões diferentes dentro da mesma controller.

5. Conclusão

O uso do versionamento, inicialmente, permite a coexistência dessas duas versões da API no mesmo endereço. Dessa forma, sistemas legados continuem a funcionar normalmente, enquanto novos sistemas ou sistemas atualizados podem optar por utilizar a versão mais recente da API.

Isso ilustra o poder e a flexibilidade do controle de versão na API do .NET, permitindo que os desenvolvedores evoluam suas APIs sem medo de quebrar sistemas existentes.

 

Legal né?!

Atributos Especiais de Informações

Olá, Devs! Primeiramente, quero dizer que hoje vou compartilhar uma dica daquelas e trata-se dos atributos especiais do C#!!!

Pois bem, você sabia que no C# temos alguns atributos especiais que são poderosos quando queremos obter informações sobre quem chamou determinado método? Isso mesmo! Estou falando dos atributos CallerMemberName, CallerFilePath e CallerLineNumber.

Além disso, eles são muito úteis para cenários de rastreamento, depuração e geração de logs.

1. Então, vamos lá! Vem comigo que eu te explico:

– CallerMemberName
Primeiramente, sabe quando você quer saber o nome daquele método que chamou o seu? Pois é, esse atributo te dá essa resposta!

– CallerFilePath
Por outro lado, esse aqui é para os detalhistas! Ele te diz o caminho exato, a localização precisa do arquivo de origem que fez a chamada.

– CallerLineNumber
Agora, imagine se eu te dissesse que há um jeito de saber a linha específica no arquivo onde o chamador fez aquela ligação para o método? É isso que esse atributo faz!

O exemplo abaixo mostra isso, ou seja, o nome do chamador, o path do arquivo e o número da linha sendo gerados, pois passamos como parâmetros do método TraceMessage os atributos CallerMemberName, CallerFilePath e CallerLineNumber.

Atributos Especiais

2. Seguindo em frente, vamos decifrar o código juntos?

1. Temos dois métodos: DoProcessing e TraceMessage.

2. O primeiro, DoProcessing, liga para o TraceMessage só para dizer: “An error happened“.

3. O TraceMessage é o nosso detetive. Via parâmetros ele está preparado não só para ouvir a mensagem, mas também para pegar três informações muito importantes que são: CallerMemberName, CallerFilePath e CallerLineNumber que pega o nome do método ou propriedade chamador, obtém o caminho completo do arquivo de origem do chamador e o número da linha do ponto onde o método foi chamado respectivamente.

E sabe o melhor? O C# faz isso automaticamente pra gente!

4. Finalmente, TraceMessage conta tudo o que descobriu usando o bom e velho Console.WriteLine.

Agora, um segredo entre nós: Não precisa se preocupar em fornecer esses detalhes ao chamar o método. É mágico! O próprio compilador cuida disso pra você. E fique tranquilo quanto à performance, porque isso acontece no momento da compilação, não quando seu código está rodando.

Portanto, meu conselho? Use e abuse desses atributos, especialmente quando estiver registrando informações. Eles te ajudam a saber exatamente de onde veio aquela mensagem ou erro, sem ter que fazer malabarismo pra descobrir.

 

E aí, o que acharam? Estão prontos para mergulhar ainda mais fundo no universo do C#?