如何在C# WebRequest中为表单值添加xml键名匹配Postman请求
问题:如何让C#生成的x-www-form-urlencoded请求包含"xml"键?
我当前的C#脚本生成的POST请求和Postman里的预期格式不一致。具体来说,Postman中我是通过选择Body→x-www-form-urlencoded,设置键名为xml、值为完整XML内容来创建请求的;但我的C#代码直接把XML内容转成字节发送,导致请求的form字段里没有"xml"这个键,反而把XML内容拆成了混乱的键值对。请问该怎么修改代码实现预期效果?
原代码
internal string sendOrder(string xml) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://httpbin.org/post"); byte[] requestInFormOfBytes = Encoding.UTF8.GetBytes(xml); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = requestInFormOfBytes.Length; Stream requestStream = request.GetRequestStream(); requestStream.Write(requestInFormOfBytes, 0, requestInFormOfBytes.Length); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader respStream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default); string receivedResponse = respStream.ReadToEnd(); Console.WriteLine(receivedResponse); respStream.Close(); response.Close(); requestStream.Close(); return receivedResponse; }
当前请求结果
{ "args": {}, "data": "", "files": {}, "form": { "<?xml version": "\"1.0\" encoding=\"UTF-8\"?><atesapiorder><auth><login></login><salt>2020-05-19 16:14:2950</salt><passfingerprint></passfingerprint></auth><header><deliveryaddresscode>ZZ05</deliveryaddresscode><buyerorderreference>olo10</buyerorderreference><remarks>opcjonalne uwagi do zam\u00f3wienia</remarks></header><lines></lines></atesapiorder>" }, "headers": { "Content-Length": "948", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", }, "json": null, "url": "https://httpbin.org/post" }
预期请求结果
{ "args": {}, "data": "", "files": {}, "form": { "xml": "<?xml version='1.0' encoding='UTF-8'?>\n<atesapiorder>\n <auth>\n <login></login>\n <salt></salt>\n <passfingerprint></passfingerprint>\n </auth>\n <header>\n <deliveryaddresscode>ZZ05</deliveryaddresscode>\n <buyerorderreference>test101111</buyerorderreference>\n <remarks>opcjonalne uwagi do zam\u00f3wienia</remarks>\n </header>\n <lines></lines>\n</atesapiorder>" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, br", "Cache-Control": "no-cache", "Content-Length": "1460", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", }, "url": "https://httpbin.org/post" }
解决方案
问题出在你没有按照x-www-form-urlencoded的规范构造请求体:这种格式要求数据是key=value的形式,而且value必须经过URL编码(避免XML里的特殊字符比如&、=破坏格式)。你之前直接把XML内容转成字节发送,相当于没有设置键名,还让XML里的特殊字符把请求体拆成了错误的键值对。
修改步骤:
- 用
HttpUtility.UrlEncode对XML内容进行URL编码,确保特殊字符被正确转义 - 构造
xml=编码后的XML内容这样的请求体字符串 - 再把这个字符串转成字节数组写入请求流
修改后的代码
using System.Web; // 若为.NET Core/.NET 5+,改用System.Net.WebUtility internal string sendOrder(string xml) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://httpbin.org/post"); // 1. 对XML内容进行URL编码,构造key=value格式的请求体 string encodedXml = HttpUtility.UrlEncode(xml, Encoding.UTF8); string requestBody = $"xml={encodedXml}"; byte[] requestInFormOfBytes = Encoding.UTF8.GetBytes(requestBody); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = requestInFormOfBytes.Length; // 使用using自动释放资源,避免内存泄漏 using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(requestInFormOfBytes, 0, requestInFormOfBytes.Length); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (StreamReader respStream = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { string receivedResponse = respStream.ReadToEnd(); Console.WriteLine(receivedResponse); return receivedResponse; } }
额外优化说明
- 我把原来的
Close()调用换成了using语句,这样可以自动释放资源,避免内存泄漏 - 如果你的项目是.NET Core或.NET 5+,
HttpUtility在System.Web程序集中不可用,此时可以改用System.Net.WebUtility.UrlEncode,用法完全一致
内容的提问来源于stack exchange,提问作者Szczepan
相关产品推荐
相关产品推荐

