为什么 Content-Type 是每个 C# 开发者的痛点?
\n\n你是否曾经通过 C# 中的 HttpClient 发送过 POST 请求,而服务器却返回了一个神秘的 415 错误(不支持的媒体类型)?很熟悉,对吧?大多数情况下,问题就出在一个微小但至关重要的标头——Content-Type 上。没有它,服务器根本不知道如何解释你的数据:是 JSON、XML 还是普通的表单数据?
在本文中,我们将探讨如何正确地为 C# 中的 HttpClient 设置 Content-Type,分析新手(甚至不仅仅是新手)最常踩的坑,并学习如何发送请求,让服务器能立刻理解你的意图。开始吧!
\n\n什么是 Content-Type,为什么需要它?
\n\nContent-Type 是一个 HTTP 标头,用于告诉服务器请求体(或响应体)中数据的格式。如果你发送 JSON,需要指定:application/json。如果是 XML,则指定 application/xml。如果是表单数据,则指定 application/x-www-form-urlencoded。
在 C# 中,HttpClient 是一个强大但狡猾的工具。它有时能自己猜出格式,有时却不能。如果你试图通过 DefaultRequestHeaders 简单地添加标头,你会遇到一个令人不快的意外:Content-Type 不属于默认请求标头。它只与请求体相关。
新手典型错误
\n\nvar client = new HttpClient();\nclient.DefaultRequestHeaders.Add("Content-Type", "application/json"); // ❌ 错误!\n\n\n这段代码会引发 InvalidOperationException 异常,并显示消息:"Misused header name. Make sure request headers are used with HttpRequestMessage, response ones with HttpResponseMessage, and content ones with HttpContent objects." 听起来很吓人,但解决方案很简单——请继续阅读。
在 C# HttpClient 中设置 Content-Type 的三种方法
\n\n方法 1:使用 StringContent(最简单)
\n\n最流行且正确的方法是通过 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 // 创建内容并显式指定 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\n在这个例子中,Content-Type: application/json; charset=utf-8 会自动设置。第二个参数(Encoding.UTF8)指定编码,第三个参数指定媒体类型。瞧——服务器满意了!
方法 2:通过 ByteArrayContent(适合高级用户)
\n\n如果你处理的是二进制数据,或者想要完全控制,可以使用 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\n这里我们通过 Headers 属性手动设置了 ContentType。当需要添加额外标头(例如 Content-Encoding)时,这种方法很方便。
方法 3:HttpRequestMessage + 完全控制
\n\n有时你需要发送带有请求体的 GET 请求(是的,这也是可以的),或者在请求级别覆盖标头。这时就轮到