HttpClient可以为GET请求发送内容或正文吗?

时间:2017-04-15 01:07:25

标签: c# get request httpclient

目前,为了向API接口发送参数化的GET请求,我正在编写以下代码:

api/master/city/filter?cityid=1&citycode='ny'

但我发现URL长度限制为2,083个字符。

为了避免这种情况,我想在内容体中以json格式发送参数以获取GET请求。

但是,我发现HttpClient的Get方法都不允许发送内容正文。对于POST,我可以看到HttpClient中有一个名为PostAsync的方法允许内容体。

有没有办法为不在URL中的GET请求发送参数以避免URL长度限制?

4 个答案:

答案 0 :(得分:12)

请阅读本答案末尾的注意事项,了解为何一般不建议使用正文的HTTP GET请求。

  • 如果您使用的是.NET 核心,则标准HttpClient可以开箱即用。例如,要发送带有JSON正文的GET请求:

    HttpClient client = ...
    
    ...
    
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Get,
        RequestUri = new Uri("some url"),
        Content = new StringContent("some json", Encoding.UTF8, ContentType.Json),
    };
    
    var response = await client.SendAsync(request).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
    
    var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    
  • .NET 框架不支持此开箱即用(您将收到ProtocolViolationException),但您可以下载并安装{{3在构造HttpClient实例时,使用它代替默认System.Net.Http.WinHttpHandler

    var handler = new WinHttpHandler();
    var client = new HttpClient(handler);
    
    <rest of code as above>
    

    参考:HttpClientHandler

注意事项:

  • 带有正文的HTTP GET是一种有点非常规的构造,属于HTTP规范的灰色区域 - 最终结果是许多较旧的软件根本无法处理这样的请求,或者会明确拒绝它,因为它们相信它是畸形的。您需要确保您尝试发送此类请求的端点支持它,或者最多您将获得HTTP错误代码;在最坏的情况下,身体将被默默地丢弃。这可能导致一些令人头疼的调试!
  • 高速缓存代理服务器,特别是较旧的代理服务器,可以仅基于URL来缓存GET请求,因为它们不期望存在主体。这可能导致最近的请求被永久缓存(这将破坏您的软件),或者唯一的缓存请求是最近发布的请求(这将阻止缓存按预期工作)。再说一遍,弄清楚这可能是非常痛苦的。

答案 1 :(得分:0)

类似于以上答案,但代码较少

var request = new HttpRequestMessage
{
    Method = HttpMethod.Get,
    RequestUri = targetUri,
    Content = new StringContent(payload.Payload),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
var responseInfo = await response.Content.ReadAsStringAsync();

答案 2 :(得分:0)

我不能使用.NET核心,也不想安装System.Net.Http.WinHttpHandler,它具有大量的依赖性。 我使用反射解决了这个问题,以欺骗WebRequest认为使用GET请求发送正文是合法的(根据最新的RFC)。我要做的是将HTTP动词“ GET”的ContentBodyNotAllowed设置为false。

var request = WebRequest.Create(requestUri);

request.ContentType = "application/json";
request.Method = "GET";

var type = request.GetType();
var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request);

var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false);

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    streamWriter.Write("<Json string here>");
}

var response = (HttpWebResponse)request.GetResponse();

但是请注意,属性ContentBodyNotAllowed属于一个静态字段,因此当其值更改时,它对于程序的其余部分仍然有效。就我而言,这不是问题。

答案 3 :(得分:0)

在我的 .Net Core 项目中花了很多时间后,HttpClientWebRequest 都无法正常工作,显然服务器没有获取我的数据,并且返回了一个错误,说明了一些特定的我的请求中没有数据。最后只有 RestSharp 在我的情况下起作用(变量 myData 是以下代码中的 Dictionary<string,string> 实例):

var client = new RestClient("some url");
var request = new RestRequest(Method.GET);
foreach (var d in myData)
    request.AddParameter(d.Key, d.Value);
var result = (await client.ExecuteAsync(request)).Content;