在使用Content-Type
执行GET
时,我是否可以明确设置HttpClient
标头值?
我意识到这会破坏1.1协议,但我正在使用不符合它的API,并且要求我设置Content-Type
标头。
我试过这个没有用......
using (var httpClient = new HttpClient())
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.com");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded+v1.3");
await httpClient.SendAsync(httpRequestMessage)
}
我在添加DefaultRequestHeaders
后检查了TryAddWithoutValidation
,似乎没有设置Content-Type
值。
如果我尝试设置httpRequestMessage的Content-Type(通过设置httpRequestMessage.Content = ...
,我会收到以下错误:
Cannot send a content-body with this verb-type.
有没有办法可以使用HttpClient为Content-Type
操作显式设置GET
?
答案 0 :(得分:6)
根据我的发现,我得出结论,HttpClient在协议规则方面非常严格。我还通过实现DLL反映,我无法找到任何表明它允许协议违规的内容。
GET请求不应具有内容类型标头,并且HttpClient正在强制执行该规则。
我认为当您尝试设置内容类型标头时,异常消息是自描述的:
System.InvalidOperationException:未使用的标题名称。确保请求标头与HttpRequestMessage一起使用,响应标头与HttpResponseMessage一起使用,内容标头与HttpContent对象一起使用。
此外,如果您使用设置内容正文,则会获得一条自我描述性消息:
System.Net.ProtocolViolationException:无法使用此动词类型发送内容正文。
由于您愿意违反GET请求的HTTP规则,因此我非常确定您唯一的选择是坚持使用限制较少的WebClient,它适用于该场景。
答案 1 :(得分:5)
可能 - 而且非常脏 - 用一些反射覆盖库行为,并引入一个DelegatingHandler
作为HttpClient
构造函数的参数。请参阅下面的代码。
public class HmacAuthenticatingHandler : DelegatingHandler
{
public HmacAuthenticatingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// HACK: Set 'Content-Type' even for GET requests
var invalidHeaders = (HashSet<string>)typeof(HttpHeaders)
.GetField("invalidHeaders", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(request.Headers);
invalidHeaders.Remove("Content-Type");
request.Headers.Remove("Content-Type");
request.Headers.Add("Content-Type", "application/json");
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
答案 2 :(得分:1)
虽然现在没有任何帮助,但看起来.NET框架的未来版本可能会通过添加AddWithoutValidation方法来支持这种类型的协议违规:
答案 3 :(得分:0)
您是否尝试过向内容标题添加标题(与请求标头一起使用) 见here
答案 4 :(得分:0)
我遇到了需要调用的API的情况,我可以通过将内容设置为空的StringContent
来解决此问题:
httpRequestMessage.Content = new StringContent("", Encoding.ASCII, "application/json");
这同时发送一个Content-Type
和一个Content-Length
头(值为0
),我正在调用的API可以使用。如果API拒绝带有Content-Length
标头的请求,则此方法将无效。
我正在使用.NET Core 3.1。看来OP使用的版本不支持在GET请求上设置Content
属性。