HttpClient.PostAsync传XML必须设Content-Type为application/xml或text/xml,用StringContent指定编码和类型;XML需良构无BOM;异步调用须用await避免死锁;响应要先检查StatusCode再读取内容。

HttpClient.PostAsync 传 XML 要设对 Content-Type
不设 Content-Type: application/xml,服务端大概率收不到或解析失败。很多同学只顾拼 XML 字符串,忘了告诉服务器“这是 XML”,结果接口返回 400 或 415 错误。
- 用
StringContent包裹 XML 字符串,显式指定编码和类型:var content = new StringContent(xmlString, Encoding.UTF8, "application/xml");
- 别用
FormUrlEncodedContent—— 它会把 XML 当成键值对转义,XML 标签全被破坏 - 如果服务端要求
text/xml,就写"text/xml";但现代 API 多数认application/xml,优先试这个
XML 字符串本身得是良构的,且避免 BOM
本地测试时从文件读 XML 再发出去,容易带 UTF-8 BOM(尤其是记事本保存的),HttpClient 会原样发出,某些服务端(如 Java Spring Boot)直接拒收。
- 用
File.ReadAllText(path, Encoding.UTF8)读取,别用Encoding.Default—— 中文 Windows 下它可能是 GBK,XML 解析必崩 - 手动检查开头是否有
<?xml,且前面没空格、换行或不可见字符;可用xmlString.TrimStart()防一手 - 如果 XML 来自
XDocument,用doc.ToString(SaveOptions.DisableFormatting),避免缩进干扰
同步调用别用 .Result,用 await 配合 ConfigureAwait(false)
在 ASP.NET Core 或 WinForms 后台线程里写 client.PostAsync(...).Result,极大概率死锁。这不是“建议异步”,而是“不这么写就跑不起来”。
- 必须用
await client.PostAsync(...),方法签名加async Task<T> - 若在非 async 上下文中(比如老式事件处理器),改用
GetAwaiter().GetResult()比.Result更安全(但仍不推荐) - 在类库中封装时,加上
.ConfigureAwait(false):await client.PostAsync(url, content).ConfigureAwait(false);
响应处理要检查 StatusCode,别直接 .ReadAsStringAsync()
HTTP 状态码不是 2xx 时,ReadAsStringAsync() 仍会返回内容(比如错误页 HTML 或 JSON 提示),但你可能以为“有返回就是成功”。
- 先判断
response.IsSuccessStatusCode,再读响应体 - 非 2xx 时,用
response.Content.ReadAsStringAsync()拿错误详情,比只看response.StatusCode有用得多 - 如果服务端返回的是 XML 错误(比如 SOAP Fault),也要按 XML 解析,不能硬当成字符串日志一扔了事
真正麻烦的从来不是“怎么发 XML”,而是服务端返回的错误信息藏在 XML 里、没文档、没示例,又不肯改接口。这时候多打一行日志输出原始响应体,比反复改 Content-Type 实在得多。










