C# 显式设置HttpClient中Get操作的内容类型头

C# 显式设置HttpClient中Get操作的内容类型头,c#,.net,dotnet-httpclient,C#,.net,Dotnet Httpclient,在使用HttpClient执行GET时,是否有一种方法可以显式设置内容类型标题值 我意识到这破坏了1.1协议,但我使用的API不符合它,需要我设置内容类型标题 我试过了,但是没有用 using (var httpClient = new HttpClient()) { var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.com"); httpClient.DefaultReq

在使用
HttpClient
执行
GET
时,是否有一种方法可以显式设置
内容类型
标题值

我意识到这破坏了1.1协议,但我使用的API不符合它,需要我设置
内容类型
标题

我试过了,但是没有用

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)
}
在添加了
TryAddWithoutValidation
之后,我检查了
DefaultRequestHeaders
,它似乎没有设置
内容类型

如果我试图设置httpRequestMessage的内容类型(通过设置
httpRequestMessage.Content=…
),我会得到以下错误:

Cannot send a content-body with this verb-type.

有没有一种方法可以让我使用HttpClient为
GET
操作显式设置
内容类型

根据我的发现,我得出结论,HttpClient在协议规则方面非常严格。我还通过实现DLL进行了反思,我找不到任何它允许的东西违反协议

GET请求不应具有内容类型头,HttpClient正在强制执行该规则

我认为当您尝试设置内容类型标题时,异常消息是自描述性的:

System.InvalidOperationException:误用了头名称。确保请求头与HttpRequestMessage一起使用,响应头与HttpResponseMessage一起使用,内容头与HttpContent对象一起使用

此外,如果使用“设置内容正文”,则会收到另一条自描述性消息:

System.Net.ProtocolViolationException:无法发送具有此动词类型的内容正文


既然你愿意违反HTTP规则来获取请求,我敢肯定你唯一的选择就是坚持使用限制性较小的WebClient,这在这种情况下是有效的。

通过一些反射和引入一个作为参数给出的
DelegatingHandler
来覆盖库行为是可能的,而且非常肮脏nt到
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)
            // use "_invalidHeaders" for System.Net.Http v2.2+
            .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;
    }
}
公共类HMACAuthenticationHandler:DelegatingHandler
{
公共HmacAuthenticatingHandler(HttpMessageHandler innerHandler)
:base(innerHandler)
{
}
受保护的覆盖异步任务SendAsync(
HttpRequestMessage请求,CancellationToken CancellationToken)
{
//HACK:甚至为GET请求设置“内容类型”
var invalidHeaders=(哈希集)typeof(HttpHeaders)
//对System.Net.Http v2.2使用“\u invalidHeaders”+
.GetField(“invalidHeaders”,BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(请求标头);
invalidHeaders.Remove(“内容类型”);
request.Headers.Remove(“内容类型”);
Add(“内容类型”、“应用程序/json”);
var response=await base.sendaync(请求、取消令牌);
返回响应;
}
}

您是否尝试将标题添加到内容标题(与请求标题一样)
请参见

尽管目前对您没有帮助,但看起来未来版本的.NET framework可能会通过添加以下方法来支持此类协议冲突:


我遇到了同样的情况,我需要调用一个API,通过将内容设置为空的
StringContent
,我可以解决这个问题:

httpRequestMessage.Content = new StringContent("", Encoding.ASCII, "application/json");
这会发送
内容类型
内容长度
头(值为
0
),我调用的API对此没有问题。如果API拒绝带有
内容长度
头的请求,这将不起作用


我正在使用.NET Core 3.1。OP使用的版本似乎不支持在GET请求上设置
内容
属性。

作为一种解决方法,我可以同时使用
WebClient
。@ZenCoder。这不会设置
内容类型
标题。只有
接受
标题。没有GE的正文T操作,因此不需要设置内容类型。如果可能的话,应该更正API。是的,对不起,我需要重复我自己-我正在集成的API不符合HTTP规范。它们需要
GET
操作,提供
内容类型
标题。对。对不起,我已经重写了我的响应。谢谢,我已经完成了d我觉得这可能是唯一的选择。感谢您的帮助,不要使用.Net Framework 4.0版,System.Net.Http 2.2.29.0版,而是使用2.0.0版。0@prem将“invalidHeaders”更改为“\u invalidHeaders”