C# .NET4.8.1发送带XML的GET请求触发ProtocolViolationException求解决
解决.NET 4.8.1中GET请求携带XML体引发的ProtocolViolationException错误
错误原因
.NET Framework的HttpClient底层依赖HttpWebRequest,默认严格遵循HTTP规范——规范中明确GET请求的语义是获取资源,不建议携带请求体,因此框架会直接拦截这类请求并抛出System.Net.ProtocolViolationException。而Postman未做严格的协议检查,所以能正常发送这类非标准请求。
解决方案
由于无法改用POST请求,我们可以直接使用HttpWebRequest替代HttpClient,并通过反射绕过框架的协议检查,实现带XML体的GET请求:
using System; using System.IO; using System.Net; using System.Reflection; class Program { static void Main(string[] args) { var requestUri = new Uri("http://XXXX/get/getFees"); var xmlBody = @"<?xml version=""1.0"" encoding=""utf-8""?> <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""> <soap:Body> </soap:Body> </soap:Envelope>"; // 创建GET请求实例 var request = (HttpWebRequest)WebRequest.Create(requestUri); request.Method = "GET"; request.ContentType = "text/plain"; // 添加授权和Cookie头 request.Headers.Add("Authorization", "Basic XXXX"); request.Headers.Add("Cookie", "JSESSIONID=XXXX"); // 反射修改私有字段,允许GET请求携带请求体 var allowRequestBodyField = typeof(HttpWebRequest).GetField("_allowRequestBody", BindingFlags.Instance | BindingFlags.NonPublic); allowRequestBodyField?.SetValue(request, true); // 将XML内容写入请求流 using (var requestStream = request.GetRequestStream()) using (var streamWriter = new StreamWriter(requestStream)) { streamWriter.Write(xmlBody); } // 获取并输出响应内容 using (var response = (HttpWebResponse)request.GetResponse()) using (var responseStream = response.GetResponseStream()) using (var streamReader = new StreamReader(responseStream)) { var responseContent = streamReader.ReadToEnd(); Console.WriteLine(responseContent); } } }
注意事项
- 这种方式属于绕过HTTP规范的非标准用法,仅在无法改用POST的场景下使用。
- 反射操作依赖.NET Framework内部实现,若框架版本更新可能出现兼容性问题,需留意后续版本变化。
内容的提问来源于stack exchange,提问作者Lucky Star
相关产品推荐
相关产品推荐

