Por que Content-Type é o pesadelo de todo desenvolvedor C#?
\n\nVocê já enviou uma requisição POST via HttpClient em C# e o servidor respondeu com um misterioso erro 415 (Unsupported Media Type)? Familiar, não é? Na maioria das vezes, o problema está em um pequeno, mas crucial cabeçalho — Content-Type. Sem ele, o servidor simplesmente não sabe como interpretar seus dados: é JSON, XML ou um formulário comum?
Neste artigo, vamos abordar como definir corretamente o Content-Type para HttpClient em C#, examinar as armadilhas mais comuns que iniciantes (e não só) enfrentam, e aprender a enviar requisições de forma que o servidor entenda perfeitamente. Vamos lá!
\n\nO que é Content-Type e para que serve?
\n\nContent-Type é um cabeçalho HTTP que indica ao servidor em qual formato os dados estão sendo transmitidos no corpo da requisição (ou resposta). Se você está enviando JSON, precisa informar: application/json. Se for XML — application/xml. Se forem dados de formulário — application/x-www-form-urlencoded.
Em C#, HttpClient é uma ferramenta poderosa, mas traiçoeira. Ele pode adivinhar o formato sozinho, ou não. E se você tentar simplesmente adicionar o cabeçalho via DefaultRequestHeaders, terá uma surpresa desagradável: Content-Type não faz parte dos cabeçalhos padrão da requisição. Ele pertence apenas ao corpo da requisição.
Erro típico de iniciante
\n\nvar client = new HttpClient();\nclient.DefaultRequestHeaders.Add("Content-Type", "application/json"); // ❌ ERRO!\n\n\nEste código lançará uma exceção InvalidOperationException com a mensagem: "Misused header name. Make sure request headers are used with HttpRequestMessage, response ones with HttpResponseMessage, and content ones with HttpContent objects." Parece assustador, mas a solução é simples — continue lendo.
Três maneiras de definir Content-Type em C# HttpClient
\n\nMétodo 1: Usar StringContent (o mais simples)
\n\nA maneira mais popular e correta é passar o cabeçalho junto com o corpo da requisição através da classe StringContent.
using System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main()\n {\n var client = new HttpClient();\n var json = "{ \\"name\\": \\"PythonLib\\", \\"type\\": \\"education\\" }";\n \n // Criando conteúdo com especificação explícita de Content-Type\n var content = new StringContent(json, Encoding.UTF8, "application/json");\n \n var response = await client.PostAsync("https://api.example.com/data", content);\n Console.WriteLine(await response.Content.ReadAsStringAsync());\n }\n}\n\n\nNeste exemplo, Content-Type: application/json; charset=utf-8 é definido automaticamente. O segundo parâmetro (Encoding.UTF8) define a codificação, o terceiro define o media type. Pronto — o servidor está satisfeito!
Método 2: Através de ByteArrayContent (para avançados)
\n\nSe você está trabalhando com dados binários ou quer controle total, use ByteArrayContent.
using System.Net.Http;\nusing System.Text;\n\nvar jsonBytes = Encoding.UTF8.GetBytes("{ \\"message\\": \\"Hello\\" }");\nvar content = new ByteArrayContent(jsonBytes);\ncontent.Headers.ContentType = new MediaTypeHeaderValue("application/json");\n\nvar response = await client.PostAsync("https://api.example.com/upload", content);\n\n\nAqui, definimos manualmente o ContentType através da propriedade Headers. Este método é útil quando você precisa adicionar cabeçalhos adicionais (por exemplo, Content-Encoding).
Método 3: HttpRequestMessage + controle total
\n\nÀs vezes, você precisa enviar uma requisição GET com corpo (sim, isso também é possível) ou sobrescrever cabeçalhos no nível da requisição. Então, em