Executando verificação de segurança...
2

Como fazer requisições em C#

Introdução

Olá pessoal, sou estudante de ciência da computação e estou aprendendo C# mas acabei tendo algumas dificuldades, a pesar de já ter visto JAVA na faculdade. Uma das minhas dificuldades compreender como que é feita uma requisição utilizando a linguagem, como sou acostumado a utilizar JavaScript senti um pouco de dificuldade, principalmente em achar algo bem explicado. Então resolvi juntar todo meu conhecimento, todas minhas pesquisas e trazer aqui uma espécie de resumo, espero que ajude, para isso utilizaremos a PokeAPI.

Sobre o C#

Como sabemos o C# é uma linguagem orientada a objetos, com essa premissa tudo é feito com o uso de classes, que possuem seus métodos e atributos, quando queremos fazer uma requisição HTTP, a algum end-point de uma API qualquer, temos que ter em mente que ela irá nos retornar na grande maioria das vezes um json, que a gente precisa converter para um objeto, geralmente usando a biblioteca NewtonSoft. Porém, apenas fazendo essa conversão não conseguiríamos acessar os campos da requisição, exemplo pokemon.nome, para ter acesso, nós precisamos criar uma classe que tenha como atributos os campos que a gente irá receber de retorno da nossa requisição, e como utilizaremos a PokeAPI, deixarei um link pronto que retorna os 3 primeiros Pokemons da primeira geração e suas respectivas evoluções. Link dos Pokemons

{
  "count": 1154,
  "next": "https://pokeapi.co/api/v2/pokemon?offset=9&limit=9",
  "previous": null,
  "results": [
    {
      "name": "bulbasaur",
      "url": "https://pokeapi.co/api/v2/pokemon/1/"
    },
    {
      "name": "ivysaur",
      "url": "https://pokeapi.co/api/v2/pokemon/2/"
    },
    {
      "name": "venusaur",
      "url": "https://pokeapi.co/api/v2/pokemon/3/"
    },
    {
      "name": "charmander",
      "url": "https://pokeapi.co/api/v2/pokemon/4/"
    },
    {
      "name": "charmeleon",
      "url": "https://pokeapi.co/api/v2/pokemon/5/"
    },
    {
      "name": "charizard",
      "url": "https://pokeapi.co/api/v2/pokemon/6/"
    },
    {
      "name": "squirtle",
      "url": "https://pokeapi.co/api/v2/pokemon/7/"
    },
    {
      "name": "wartortle",
      "url": "https://pokeapi.co/api/v2/pokemon/8/"
    },
    {
      "name": "blastoise",
      "url": "https://pokeapi.co/api/v2/pokemon/9/"
    }
  ]
}

Como mencionei anteriormente, temos que criar uma ou mais classes onde os parâmetros serão os campos das requisições.

Converter Automaticamente

Existe um site que ajuda bastante na criação dessas classes segue o link. Quicktype

Criando Classe Pokemon

namespace ConsumoAPI
{
    internal class Pokemon 
    {
        [JsonProperty("count")]
        public long Count { get; set; }

        [JsonProperty("next")]
        public object Next { get; set; }

        [JsonProperty("previouns")]
        public object Previous { get; set; }

        [JsonProperty("results")]
        public List<Result> Results { get; set; }
	}
}

A cima são os atributos da classe, mas o que é esse JsonProperty?
Quando utilizamos o JsonProperty estamos dizendo ao C# que o atributo X é um dado Y que vem de um campo Json.

Podemos perceber que em Result no código a cima, nós tempos uma lista, mas que lista é essa?
Essa lista é um campo que vem em formato de Array/List dentro da requisição.
Certo, mas a final, é uma lista de quê?
E o que tem dentro dela?

Para mostrar para o C# isso, nós temos que criar uma classe do tipo Result assim o C# entende que essa lista é de um determinado tipo, e esse tipo é o tipo Result, utilizei esse nome, pois é o nome do campo no Json, como podemos perceber o Json vem com um array de objetos "Pokemons" chamados results.


namespace ConsumoAPI
{
    internal class Pokemon
    {
        [JsonProperty("count")]
        public long Count { get; set; }
        
        [JsonProperty("next")]
        public object Next { get; set; }
        
        [JsonProperty("previouns")]
        public object Previous { get; set; }
        
        [JsonProperty("results")]
        public List<Result> Results { get; set; }
        
        // Pelo que eu entendi partial é considerado uma classe que faz parte de outra classe. 
        
	public partial class Result
        {
            [JsonProperty("name")]
            public string Name { get; set; }

            [JsonProperty("url")]
            public Uri Url { get; set; }
        }
    }
}

Feito isso, agora temos a classe no formato do retorno da requisição, precisamos criar um método que irá fazer a requisição, mas existem algumas ressalvas, para podermos acessar esse método no nosso programa, na classe Main sem precisar criar um objeto da nossa classe, então teremos que criar um método estático que será assíncrono, pois precisamos esperar o retorno da requisição.

Como sabemos, leva um pequeno tempo, até a requisição chegar no servidor e eles no retornarem os dados, que pedimos .

O método que criaremos será do tipo Task, que informa para o C# que é uma tarefa que irá ser executada em outra Thread, mas não precisamos nos preocupar com isso por agora.

Método

public static async GetALLPokemons(){
	Uri url = new Uri("https://pokeapi.co/api/v2/pokemon?limit=151&offset=0");
	Httpclient client = new HttpClient();
        
	//aqui fazempos a requisição do tipo get asyncrona
	var response = await client.GetAsync(url);
	if(response.IsSuccessStatusCode){
		var result = await response.Content.ReadAsStringAsync();
		
		/* 
			Aqui dizemos que a variável lista é do tipo POKEMON e ela vai receber
			o resultado da deserilzação, meio que ele vai converter o Json que recebemos
			em um objeto, e depois irá atribuir os campos desse Json a um objeto 
		 */ 
		var listaDePokemon = JsonConvert.DeserializeObject<Pokemon>(result);
		
		//para cada pokemon na lista de pokemon ele irá mostrar o nome e a url
		foreach(var poke in listaDePokemon.Results)
		{
			Console.WriteLine("\n--------------------------------------------------\n" + 
			"Nome: " + poke.Name + "\n" +
                        "Url: " + poke.Url);
		}
	}
}

Pronto agora só precisamos ir no nosso programa principal e utilizar o método, temos que dizer para nossa função superior, a que a gente está colocando o await dentro, informamos para ela que ela irá ser do tipo async e também do tipo Task.

Código completo

namespace ConsumoAPI
{
//classe do programa principal
	class Program
	{
		static async Task Main(String[] args)
		{
			await Pokemon.GetAllPokemon();
		}
	}

//classe pokemon
	internal class Pokemon
    {
        [JsonProperty("count")]
        public long Count { get; set; }

        [JsonProperty("next")]
        public object Next { get; set; }

        [JsonProperty("previouns")]
        public object Previous { get; set; }

        [JsonProperty("results")]
        public List<Result> Results { get; set; }

        //metodos
        public static async Task GetAllPokemons()
        {
            Uri url = new Uri("https://pokeapi.co/api/v2/pokemon?limit=151&offset=0");

            HttpClient client = new HttpClient();
            var response = await client.GetAsync(url);
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadAsStringAsync();

                var listaPokemon = JsonConvert.DeserializeObject<Pokemon>(result);

                foreach(var poke in listaPokemon.Results)
                {
                    Console.WriteLine("\n--------------------------------------------------\n" +
                        "Nome: " + poke.Name + "\n" +
                        "Url: " + poke.Url);

                }

                 
            }

        }

        public partial class Result
        {
            [JsonProperty("name")]
            public string Name { get; set; }

            [JsonProperty("url")]
            public Uri Url { get; set; }
        }
    }
}

ViaCEP

Aqui está mais um exemplo de API que podemos utilizar. ViaCep. Aqui nós temos que passar um código como parâmetro, para a API processar e nos retornar os dados desse determinado lugar.

Neste exemplo eu não irei dar detalhes do código pois é basicamente isgual ao código anterior, o que precisamos entender é que, temos que ter uma classe que dever ter os mesmos parâmetros que os campos que vem no Json da requisição, e um método que faz a requisição.

Só que no exemplo a cima, nós recebemos o CEP como parâmetro no programa principal, ou seja, quando chamamos o método estático GetCity temos que passar uma String contendo o código co CEP como parâmetro.

internal class ViaCep
    {
    
        public static async Task GetCity(string cep)
        {
            Uri url = new Uri("https://viacep.com.br/ws/"+ cep +"/json/");
            HttpClient client = new HttpClient();
            try
            {
                var response = await client.GetAsync(url);
                var content = await response.Content.ReadAsStringAsync();
                
                var cidade = JsonConvert.DeserializeObject<Cidade>(content);

                Console.WriteLine(cidade.Localidade);

            }catch(Exception e)
            {
                Console.WriteLine(e);
            }

        }
    }

    public partial class Cidade
    {
       public string? Cep { get; set; }
       public string? Logadouro { get; set; }
       public string? Complemento { get; set; }
       public string? Localidade { get; set; }
       public string? Bairro { get; set; }
       public string? Uf { get; set; }
       public string? Ibge { get; set;}
       public string? Gia { get; set;}
       public string? Ddd { get; set;}
       public string? Siafi { get; set;}
}
Carregando publicação patrocinada...
1