我需要使用第三方网络API 在这个特定的端点上,我需要使用内容主体(json)进行GET请求。
var jsonPayload = JsonConvert.SerializeObject(myObject);
var request = new HttpRequestMessage(HttpMethod.Get, endpoint)
{
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
};
var client = new HttpClient();
var response = await client.SendAsync(request); //<-- explodes with net461,
//but works with netstandard2.0
var responseContent = await response.Content.ReadAsStringAsync();
我将该代码定位到netstandard2.0
并且它有效
但是我现在需要在我定位net461
的项目中使用,并抛出异常说“Cannot send a content-body with this verb-type”
我知道将内容设置为GET请求并不常见,但api超出了我的职责范围。
HttpClient.Send(request)
时,net461
怎么会失败,但是当我定位netstandard2.0
时效果很好?net461
时,我有哪些选项?重现的方法。
ConsoleApp.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework> <!-- toggle this to net461 -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>
Program.cs的
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Text;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var jsonPayload = JsonConvert.SerializeObject(new { });
var request = new HttpRequestMessage(HttpMethod.Get, "http://www.stackoverflow.com")
{
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")
};
var client = new HttpClient();
var response = client.SendAsync(request).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseContent);
}
}
}
dotnet --version
显示2.1.104
答案 0 :(得分:3)
您没有提及在运行时运行它的.net版本(因为您可以定位网络标准但不能在网络标准上运行)。所以我假设当它运行时你在.NET Core上运行它,当它不运行时你就像你说的那样在完整的.NET 4.6.1上运行。
然后,这只是因为它在.NET Core和完整的.NET Framework中的实现方式不同,如本issue所述。这两种实现都没有错,因为RFC说:
GET请求消息中的有效负载没有定义的语义;
在GET请求上发送有效载荷主体可能会导致一些现有的 拒绝请求的实现。
因此,在GET中拥有主体(虽然几乎从不是一个好的实践)本身并不与RFC相矛盾。一个实现(较旧的)旨在拒绝它,但另一个(较新的)旨在允许它,没有更多的东西。
至于你的第二个问题“当我定位net461时,我有什么选择”。我不认为有简单的解决方法,因为这是HttpWebRequest
的行为,而不是HttpClient
的行为。几乎所有发出Web请求的内容都使用HttpWebRequest
。
虽然有丑陋的黑客使用反射。您的示例可以像这样修改(仅在完整.NET上运行时才有效):
static void Main(string[] args) {
// UGLY HACK!
var verbType = typeof(HttpWebRequest).Assembly.GetType("System.Net.KnownHttpVerb");
var getMethodField = verbType.GetField("Get", BindingFlags.Static | BindingFlags.NonPublic);
var getMethod = getMethodField.GetValue(null);
verbType.GetField("ContentBodyNotAllowed", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(getMethod, false);
var jsonPayload = JsonConvert.SerializeObject(new { });
var request = new HttpRequestMessage(HttpMethod.Get, "http://www.stackoverflow.com")
{
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")
};
var client = new HttpClient();
var response = client.SendAsync(request).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseContent);
}
基本上我们使用反射将ContentBodyNotAllowed
的名为KnownHttpVerb.Get
的内部字段修改为false。使用风险自负。