.NET中使用GET发送JSON触发Cannot send a content-body错误
问题描述
我用以下代码调用外部REST API时,SendAsync()抛出了**"Cannot send a content-body with this verb-type."**错误:
var request = new HttpRequestMessage( HttpMethod.Get, url ); request.Content = new StringContent( json, Encoding.UTF8, "application/json" ); client.SendAsync(request);
这个外部API要求用GET方法接收JSON数据,虽然不符合REST规范,但在Postman中可以正常运行。API文档细节如下:
Method: GET
URL: http://server/api/organization/status/39bd8abc-6022-44e9-8a70-ed4830b8afc1
Authentication: Bearer
Header:
Key: X-Request-Partner
Value: 7e884abc-2cd9-4990-a559-18f7def375e9
Body (raw JSON):
{ "Fields": [ { "Name": "IdPerson", "ObjectType": "Person" }, { "Name": "IdCard", "ObjectType": "PersonBadgeNumber" }, { "Name": "BookingDateTime", "ObjectType": "DataExchangePersonalStatusLastBookingTime" }, { "Name": "TerminalApiKey", "ObjectType": "DataExchangePersonalStatusLastTerminal", "Representation": "Naming" }, { "Name": "Status", "ObjectType": "DataExchangePersonalStatusActual", "Replacements": { "DefaultValue": "Abwesend", "ReplaceBy": [ { "SearchValue": "Present", "ReplaceBy": "Anwesend" } ] } } ] }
解决方案
.NET的HttpClient默认会阻止GET请求携带请求体,这是遵循HTTP规范的行为,但针对这类非常规API,可通过以下方式实现需求:
方法一:反射绕过HttpClient检查
通过反射修改HttpClientHandler的私有配置,允许GET请求带Body:
var handler = new HttpClientHandler(); // 调用私有方法开启GET请求允许带Body的配置 var allowGetBodyMethod = typeof(HttpClientHandler).GetMethod( "AllowGetRequestBody", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance ); allowGetBodyMethod.Invoke(handler, new object[] { true }); var client = new HttpClient(handler); var request = new HttpRequestMessage(HttpMethod.Get, url); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); // 添加API要求的请求头 request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "你的Bearer令牌"); request.Headers.Add("X-Request-Partner", "7e884abc-2cd9-4990-a559-18f7def375e9"); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync();
方法二:使用HttpWebRequest(兼容全.NET版本)
HttpWebRequest不会限制GET请求的请求体,直接使用即可:
var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.ContentType = "application/json"; // 添加请求头 request.Headers["Authorization"] = "Bearer 你的Bearer令牌"; request.Headers["X-Request-Partner"] = "7e884abc-2cd9-4990-a559-18f7def375e9"; // 写入JSON请求体 using (var streamWriter = new StreamWriter(request.GetRequestStream())) { streamWriter.Write(json); streamWriter.Flush(); } // 获取响应 using (var response = (HttpWebResponse)request.GetResponse()) using (var streamReader = new StreamReader(response.GetResponseStream())) { var responseContent = streamReader.ReadToEnd(); }
方法三:手动设置ContentLength(.NET Core 3.0+)
在.NET Core 3.0及以上版本,可通过手动设置ContentLength绕过检查:
var request = new HttpRequestMessage(HttpMethod.Get, url); var content = new StringContent(json, Encoding.UTF8, "application/json"); request.Content = content; // 手动赋值ContentLength,绕过默认检查逻辑 request.Content.Headers.ContentLength = content.Headers.ContentLength; // 添加请求头 request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "你的Bearer令牌"); request.Headers.Add("X-Request-Partner", "7e884abc-2cd9-4990-a559-18f7def375e9"); var client = new HttpClient(); var response = await client.SendAsync(request);
内容的提问来源于stack exchange,提问作者Powerslave
相关产品推荐
相关产品推荐

