Cliente HTTP em C#: fazendo requisições corretamente do A ao Z
\n\nNo desenvolvimento moderno na plataforma .NET, trabalhar com requisições HTTP é uma das tarefas principais. Seja para integração com uma API REST externa, envio de dados para um servidor ou download de páginas web — o uso correto do HttpClient em C# é crítico para o desempenho e a estabilidade da aplicação. Neste artigo, abordaremos todos os aspectos do trabalho com o cliente HTTP em C#: desde exemplos básicos até técnicas avançadas, tratamento de erros e melhores práticas.
1. Fundamentos do trabalho com HttpClient em C#
\n\nHttpClient é a classe principal no .NET para enviar requisições HTTP e receber respostas. Ela está no namespace System.Net.Http e está disponível desde o .NET Framework 4.5 e todas as versões do .NET Core/.NET 5+.
Regra importante: HttpClient foi projetado para reutilização. Criar uma nova instância para cada requisição é um antipadrão que pode levar ao esgotamento de sockets (socket exhaustion). Em vez disso, use uma única instância estática ou singleton.
Exemplo básico de requisição GET:
\n\nusing System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\n\nclass Program\n{\n private static readonly HttpClient client = new HttpClient();\n\n static async Task Main(string[] args)\n {\n try\n {\n HttpResponseMessage response = await client.GetAsync("https://api.example.com/data");\n response.EnsureSuccessStatusCode();\n string responseBody = await response.Content.ReadAsStringAsync();\n Console.WriteLine(responseBody);\n }\n catch (HttpRequestException e)\n {\n Console.WriteLine($"Erro na requisição: {e.Message}");\n }\n }\n}\n\nNeste exemplo, criamos um HttpClient estático, enviamos uma requisição GET, verificamos o sucesso da resposta com EnsureSuccessStatusCode() e lemos o corpo da resposta como string.
2. Tipos de requisições HTTP e trabalho com cabeçalhos
\n\nAlém do GET, o HttpClient suporta todos os métodos HTTP principais: POST, PUT, DELETE, PATCH e outros. Vamos analisar o envio de uma requisição POST com dados JSON — este é o cenário mais comum ao trabalhar com APIs REST.
Exemplo de requisição POST com JSON:
\n\nusing System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Text.Json;\nusing System.Threading.Tasks;\n\nclass Program\n{\n private static readonly HttpClient client = new HttpClient();\n\n static async Task Main(string[] args)\n {\n var data = new { Name = "John", Age = 30 };\n string json = JsonSerializer.Serialize(data);\n var content = new StringContent(json, Encoding.UTF8, "application/json");\n\n try\n {\n HttpResponseMessage response = await client.PostAsync("https://api.example.com/users", content);\n response.EnsureSuccessStatusCode();\n string result = await response.Content.ReadAsStringAsync();\n Console.WriteLine($"Usuário criado: {result}");\n }\n catch (HttpRequestException e)\n {\n Console.WriteLine($"Erro: {e.Message}");\n }\n }\n}\n\nTrabalho com cabeçalhos: Frequentemente, as APIs exigem o envio de tokens de autenticação ou outros cabeçalhos. Eles podem ser adicionados de duas maneiras:
\n\n- \n
- Globalmente — através da propriedade
DefaultRequestHeaders(para todas as requisições do cliente). \n - Localmente — através da coleção
Headersno objetoHttpRequestMessage(para uma requisição específica). \n
Exemplo de adição do cabeçalho Authorization:
\n\n// Globalmente\nclient.DefaultRequestHeaders.Authorization = \n new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "seu-token");\n\n// Localmente\nvar request = new HttpR