如何为HttpClient请求设置Content-Type标头?

How to set the Content-Type header for an HttpClient request?

提问人:mynameiscoffey 提问时间:5/21/2012 最后编辑:Alexander Abakumovmynameiscoffey 更新时间:11/17/2023 访问量:1375575

问:

我正在尝试根据我调用的 API 的要求设置对象的标头。Content-TypeHttpClient

我尝试设置如下:Content-Type

using (var httpClient = new HttpClient())
{
    httpClient.BaseAddress = new Uri("http://example.com/");
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
    // ...
}

它允许我添加标题,但是当我尝试添加时,它会引发以下异常:AcceptContent-Type

误用的标头名称。确保请求标头与 、 响应标头和 一起使用 带有对象的内容标头。HttpRequestMessageHttpResponseMessageHttpContent

如何在请求中设置标头?Content-TypeHttpClient

C# asp.net REST 内容类型 dotnet-httpclient

评论

1赞 jiping-s 8/27/2018
可以遵循 .NET Core 中的 HttpWebRequest 如何执行(它在内部使用 HttpClient),请参阅 github.com/dotnet/corefx/blob/master/src/System.Net.Requests/...“SendRequest”方法

答:

21赞 Robert Levy 5/21/2012 #1

代替 Call(请参阅此 MSDN 链接)。AddWithoutValidationAdd

或者,我猜您使用的 API 实际上只需要 POST 或 PUT 请求(而不是普通的 GET 请求)。在这种情况下,当您调用并传入 时,请在该对象的属性上设置此项。HttpClient.PostAsyncHttpContentHeadersHttpContent

评论

5赞 KansaiRobot 6/12/2018
AddWithoutValidation 不存在
0赞 TommyJ 9/1/2023
我相信这意味着 TryAddWithoutValidation;完整引用是 System.Net.Http.Headers.HttpHeaders.TryAddWithoutValidation。
1374赞 carlosfigueira 5/21/2012 #2

内容类型是内容的标头,而不是请求的标头,这就是失败的原因。Robert Levy 建议的 AddWithoutValidation 可能有效,但您也可以在创建请求内容本身时设置内容类型(请注意,代码片段在两个位置添加 - 用于 Accept 和 Content-Type 标头):application/json

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
      .Accept
      .Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
                                    Encoding.UTF8, 
                                    "application/json");//CONTENT-TYPE header

client.SendAsync(request)
      .ContinueWith(responseTask =>
      {
          Console.WriteLine("Response: {0}", responseTask.Result);
      });

评论

50赞 John Gietzen 11/12/2012
或者,大部分时间都会工作。Response.Content.Headers
8赞 jerhewet 10/31/2014
@AshishJain 我看到的大多数涉及 ASP.Net Web API 的 SO 答案也不起作用,但如果需要,您可以轻松地使用它进行设置。Response.Content.HeadersHttpContext.Current.Response.ContentType
11赞 Ashish-BeJovial 10/31/2014
@jerhewet我以下对我有用的方式使用。var content = new StringContent(data, Encoding.UTF8, “application/json”);
33赞 Julian Reschke 5/15/2015
Content-Type 是具有有效负载的 HTTP 消息的属性;它与请求与响应无关。
17赞 Bill Noel 10/3/2016
有趣。我尝试使用三个参数创建一个新的 StringContent,但它不起作用。然后我手动:请求。Content.Headers.Remove(“Content-Type”),然后:请求。Content.Headers.Add(“Content-Type”, “application/query+json”) 并且它起作用了。奇怪。
229赞 archgl 6/6/2013 #3
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

评论

0赞 John Meyer 7/14/2016
我不得不扔.ToString() ,但是是的,这适用于 WCF 服务实现。
5赞 granadaCoder 12/21/2018
我最终会弄清楚“req”是什么对象类型......通过反复试验........但是,如果能证明这一点,那就太好了。感谢您的考虑。
0赞 granadaCoder 12/22/2018
来自“microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Http.dll”的System.Net.Http.HttpRequestMessage是我找到它的地方。
6赞 I Stand With Israel 1/19/2019
正如人们所知道的,如果尝试设置字符集,使用 MediaTypeHeaderValue 将返回错误,如下所示;response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml; charset=utf-8");
63赞 Todd Menier 6/22/2014 #4

如果你不介意一个小的库依赖,Flurl.Http [披露:我是作者]使这变得超级简单。它的方法负责序列化内容和设置标头,并反序列化响应。如果需要标头,则需要自己设置,但 Flurl 也提供了一种非常干净的方法:PostJsonAsynccontent-typeReceiveJsonaccept

using Flurl.Http;

var result = await "http://example.com/"
    .WithHeader("Accept", "application/json")
    .PostJsonAsync(new { ... })
    .ReceiveJson<TResult>();

Flurl 在后台使用 HttpClient 和 Json.NET,它是一个 PCL,因此它可以在各种平台上工作。

PM> Install-Package Flurl.Http

评论

2赞 Vlado Pandžić 3/2/2017
如果内容是application/x-www-form-urlencoded,如何发送?
48赞 SharpCoder 11/20/2015 #5

尝试使用 TryAddWithoutValidation

  var client = new HttpClient();
  client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");

评论

7赞 Martin Lietz 1/5/2018
不工作给了我一个“误用的标头名称。确保请求标头与 HttpRequestMessage 一起使用,响应标头与 HttpResponseMessage 一起使用,内容标头与 HttpContent 对象一起使用。
3赞 granadaCoder 12/22/2018
那些报告“工作”或“不工作”的人,HttpClient 现在是一个非常模棱两可的对象。请报告它来自的全名(空格)和 .dll 程序集。
0赞 ps2goat 2/6/2019
该错误已通过 dotnet Core 2.2 确认。我不得不 stackoverflow.com/a/10679340/2084315 使用@carlosfigueira的答案。Misused header name
46赞 erdomke 12/20/2016 #6

.Net 试图强制您遵守某些标准,即只能在包含内容(例如 、 等)的请求上指定标头。因此,正如其他人所指出的,设置标头的首选方法是通过 HttpContent.Headers.ContentType 属性。Content-TypePOSTPUTContent-Type

话虽如此,某些 API(例如截至 2016 年 12 月 19 日的 LiquidFiles Api)需要设置请求的标头。.Net 不允许在请求本身上设置此标头 -- 即使使用 .此外,您不能为请求指定 a,即使它的长度为零。我似乎唯一能解决这个问题的方法就是诉诸反思。代码(以防其他人需要它)是Content-TypeGETTryAddWithoutValidationContent

var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
    .GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) 
  ?? typeof(System.Net.Http.Headers.HttpRequestHeaders) 
    .GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
  var invalidFields = (HashSet<string>)field.GetValue(null);
  invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");

编辑:

如注释中所述,此字段在不同版本的 dll 中具有不同的名称。在 GitHub 上的源代码中,该字段当前名为 .根据 @David Thompson 的建议,该示例已被修改以说明这一点。s_invalidHeaders

评论

0赞 prem 1/25/2017
不适用于 .Net Framework 版本 4.0、System.Net.Http 版本 2.2.29.0,但适用于 2.0.0.0
1赞 David Thompson 3/21/2017
此字段现在已s_invalidHeaders,因此使用以下命令可确保兼容性: var field = typeof(System.Net.Http.Headers.HttpRequestHeaders) 。GetField(“invalidHeaders”, System.Reflection.BindingFlags.NonPublic |System.Reflection.BindingFlags.Static) ??typeof(System.Net.Http.Headers.HttpRequestHeaders) 。GetField(“s_invalidHeaders”, System.Reflection.BindingFlags.NonPublic |System.Reflection.BindingFlags.Static);
0赞 GDroid 7/11/2019
很棒的黑客。但是,第一次它不应用JSON标头,而是应用所有后续调用。有人有过类似的行为吗?我确实解决了它,但有什么好的技巧吗?
0赞 DesertFoxAZ 5/5/2020
我注意到,如果我在调用第三方 API 的 API 中使用它,则第一个请求成功,但后续请求失败,除非重新启动 IIS,否则我无法让它再次工作。
0赞 nuander 3/15/2022
使用它的问题在于,它会破坏所有其他没有此问题的 API 调用。我认为是因为完成这项工作所需的 BindingFlags.Static。
26赞 Jay 6/12/2017 #7

有关 .NET Core 的一些额外信息(在阅读了 erdomke 关于设置私有字段以在没有内容的请求上提供内容类型的帖子后):

调试代码后,我看不到要通过反射设置的私有字段 - 所以我想我会尝试重现问题。

我尝试了使用 .NET 4.6 的以下代码:

HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpClient client = new HttpClient();
Task<HttpResponseMessage> response =  client.SendAsync(httpRequest);  //I know I should have used async/await here!
var result = response.Result;

而且,正如预期的那样,我得到了内容的聚合异常

无法发送具有此谓词类型的内容正文。

但是,如果我对 .NET Core (1.1) 执行相同的操作,则不会出现异常。我的服务器应用程序非常高兴地回答了我的请求,并且选择了内容类型。

4赞 art24war 5/28/2018 #8
var content = new JsonContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));

这都是你所需要的。

使用 Newtonsoft.Json,如果需要将内容作为 json 字符串。

public class JsonContent : HttpContent
   {
    private readonly MemoryStream _stream = new MemoryStream();
    ~JsonContent()
    {
        _stream.Dispose();
    }

    public JsonContent(object value)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
        {
            var serializer = new JsonSerializer();
            serializer.Serialize(jw, value);
            jw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;

    }

    private JsonContent(string content)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var sw = new StreamWriter(contexStream))
        {
            sw.Write(content);
            sw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;
    }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return _stream.CopyToAsync(stream);
    }

    protected override bool TryComputeLength(out long length)
    {
        length = _stream.Length;
        return true;
    }

    public static HttpContent FromFile(string filepath)
    {
        var content = File.ReadAllText(filepath);
        return new JsonContent(content);
    }
    public string ToJsonString()
    {
        return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
    }
}

评论

2赞 Alejandro 5/28/2018
你能简单解释一下它的作用吗?
2赞 Randall Flagg 8/22/2018
第一行失败,并显示 CS0144:“无法创建抽象类或接口 'HttpContent' 的实例”
1赞 art24war 11/21/2018
然后HttpMessageHandler handler = new WebRequestHandler(); HttpResponseMessage result; using (var client = (new HttpClient(handler, true))) { result = client.PostAsync(fullUri, content).Result; }
3赞 Ziba Leah 7/10/2018 #9

好的,它不是 HTTPClient,但如果您可以使用它,WebClient 非常简单:

using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }
0赞 leocrimson 6/12/2019 #10

我发现它最简单易懂的方式如下:

async Task SendPostRequest()
{
    HttpClient client = new HttpClient();
    var requestContent = new StringContent(<content>);
    requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    var response = await client.PostAsync(<url>, requestContent);
    var responseString = await response.Content.ReadAsStringAsync();
}
...

SendPostRequest().Wait();
7赞 Kumaran 7/10/2019 #11

你可以使用它,这将是工作!

HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();

string json = await response.Content.ReadAsStringAsync();

评论

1赞 codeMonkey 6/9/2021
这仅适用于 .NET Core,不适用于 .NET Framework。
1赞 user890332 8/10/2019 #12

你需要这样做:

    HttpContent httpContent = new StringContent(@"{ the json string }");
    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                
    HttpResponseMessage message = client.PostAsync(@"{url}", httpContent).Result;
33赞 Hassan Faghihi 8/18/2019 #13

对于那些烦恼的人charset

我有一个非常特殊的情况,服务提供商不接受字符集,他们拒绝更改子结构以允许它...... 不幸的是,HttpClient 通过 StringContent 自动设置标头,无论您是传递 null 还是 Encoding.UTF8,它都将始终设置字符集......

今天我正处于更改子系统的边缘;从 HttpClient 移动到其他任何东西,我想到了一些东西......,为什么不使用反射来清空“字符集”呢?... 在我尝试之前,我想到了一种方法,“也许我可以在初始化后更改它”,这奏效了。

以下是如何设置确切的“application/json”标头,而不使用“;字符集=UTF-8”。

var jsonRequest = JsonSerializeObject(req, options); // Custom function that parse object to string
var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType.CharSet = null;
return stringContent;

注意:以下值将不起作用,并附加“;字符集=utf-8”null

return new StringContent(jsonRequest, null, "application/json");

编辑

@DesertFoxAZ建议也可以使用以下代码并且工作正常。(我自己没有测试过,如果它有效,请在评论中称赞他)

stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

评论

2赞 DesertFoxAZ 4/17/2020
stringContent.Headers.ContentType = new MediaTypeHeaderValue(“application/json”);也有效
3赞 Felipe Augusto 3/1/2021 #14

尝试使用 HttpClientFactory

services.AddSingleton<WebRequestXXX>()
        .AddHttpClient<WebRequestXXX>("ClientX", config =>
        {
           config.BaseAddress = new System.Uri("https://jsonplaceholder.typicode.com");
           config.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
           config.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
        });

======================

public class WebRequestXXXX
{
    private readonly IHttpClientFactory _httpClientFactory;

    public WebRequestXXXX(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public List<Posts> GetAllPosts()
    {
        using (var _client = _httpClientFactory.CreateClient("ClientX"))
        {
            var response = _client.GetAsync("/posts").Result;

            if (response.IsSuccessStatusCode)
            {
                var itemString = response.Content.ReadAsStringAsync().Result;
                var itemJson = System.Text.Json.JsonSerializer.Deserialize<List<Posts>>(itemString, 
                    new System.Text.Json.JsonSerializerOptions 
                    {
                        PropertyNameCaseInsensitive = true
                    });

                return itemJson;
            }
            else
            {
                return new List<Posts>();
            }
        }
    }
}

评论

0赞 Joel Mueller 11/2/2022
是的,但在反序列化 json 时,永远不要使用 ReadAsStringAsync。使用 ReadAsStream,并反序列化流。
5赞 yoel halb 3/3/2021 #15

对于需要 Get 等内容类型标头的任何人,虽然在较旧的 .NET 版本中可以使用 https://stackoverflow.com/a/41231353@erdomke 的答案,但不幸的是,这在较新的 .NET Core 版本中不再有效。

以下代码已经过测试,适用于 .NET Core 3.1,从 GitHub 上的源代码来看,它似乎也适用于较新的 .NET 版本。

private void FixContentTypeHeaders()
{
    var assembly = typeof(System.Net.Http.Headers.HttpRequestHeaders).Assembly;
    var assemblyTypes = assembly.GetTypes();

    var knownHeaderType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeader");
    var headerTypeField = knownHeaderType?
                .GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                .FirstOrDefault(n => n.Name.Contains("HeaderType"));
    if (headerTypeField is null) return;

    var headerTypeFieldType = headerTypeField.FieldType;            
    var newValue = Enum.Parse(headerTypeFieldType, "All");

    var knownHeadersType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeaders");
    var contentTypeObj = knownHeadersType.GetFields().FirstOrDefault(n => n.Name == "ContentType").GetValue(null);

    if (contentTypeObj is null) return;

    headerTypeField.SetValue(contentTypeObj, newValue);
}

评论

1赞 ProgrammingLlama 3/3/2021
为什么所有这些反思都是必要的?它是决定 Content-Type 的内容对象,您可以在 GET 请求以及 POST、PUT 等上添加内容对象。如果您没有内容对象(正文),则 Content-Type 是一个不相关的标头。
0赞 yoel halb 3/5/2021
@John 有些框架包括Microsoft自己的框架,即使是 Get 也需要标头,即使没有 Content,也不要问我为什么。以及为什么他们的客户端在他们的服务器期望它时删除它......
0赞 ProgrammingLlama 3/5/2021
除非 Content-Length 标头存在问题,否则创建一个允许您指定标头的派生对象而不是执行所有这些反射不是更好吗?HttpContent
3赞 Sérgio Damasceno 4/21/2021 #16

我用 RestSharp 得到了答案:

private async Task<string> GetAccessTokenAsync()
{
    var client = new RestClient(_baseURL);

    var request = new RestRequest("auth/v1/login", Method.POST, DataFormat.Json);

    request.AddHeader("Content-Type", "application/json");
    request.AddHeader("x-api-key", _apiKey);
    request.AddHeader("Accept-Language", "br");
    request.AddHeader("x-client-tenant", "1");

    ...
}

它对我有用。

评论

0赞 wut 12/13/2022
但是您正在将标头添加到请求,而不是客户端
2赞 zawar 7/18/2021 #17

对于那些想要将 Content-Type 专门设置为 Json 的用户,可以使用扩展方法 PostAsJsonAsync。

using System.Net.Http.Json; //this is needed for PostAsJsonAsync to work
//....
HttpClient client = new HttpClient();
HttpResponseMessage response = await
    client.PostAsJsonAsync("http://example.com/" + "relativeAddress",
                new
                {
                    name = "John Doe",
                    age = 33
                });
//Do what you need to do with your response

这样做的好处是代码更简洁,你可以避免字符串化的json。更多细节可以在以下位置找到:https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944339(v=vs.118)

评论

3赞 Garr Godfrey 12/12/2021
我遇到的问题是PostAsJsonAsync没有设置标头!Content-type
21赞 Roland 1/5/2022 #18

诀窍是您可以设置各种标头,例如:

HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Add("Accept-Language", "en"); //works OK

但不是任何标头。例如:

request.Headers.Add("Content-Type", "application/json");//wrong

将引发运行时异常。这似乎会起作用:Misused header name

request.Headers.Add(
   HttpRequestHeader.ContentType.ToString(), //useless
   "application/json"
);

但这给出了一个无用的标头,名为 ,没有连字符。标头名称不区分大小写,但非常区分连字符。ContentType

解决方案是在将正文添加到 http 请求的 Content 部分时声明正文的编码和类型:

string Body = "...";
request.Content = new StringContent(Body, Encoding.UTF8, "application/json");

只有这样,适用的 http 标头才会自动添加到请求中,例如:

Content-Type: application/json; charset=utf-8

使用 Fiddler,在没有代理服务器的机器上很难找到这一点。Visual Studio 曾经有一个网络工具,可以在其中检查所有标头,但仅在版本 2015 中,而不是在较新版本的 2017 或 2022 中。如果使用调试器进行检查,则不会找到 自动添加的标头。request.HeadersStringContent()

评论

0赞 Xserge 12/26/2022
对于某些标头,删除“-”有效,例如请求。Headers.Add(“内容类型”, “应用程序/json”)
0赞 Roland 12/26/2022
@Xserge “作品”是什么意思?当然,这不会给出构建错误。但是服务器不会识别您的 ContentType 标头来设置内容类型,正如我在回答中解释的那样。
0赞 Xserge 12/26/2022
有些服务器会这样做,尤其是旧的CMS系统。事实上,HttpRequestHeader.ContentType.ToString() 生成“ContentType”。
2赞 Roland 12/26/2022
@Xserge当然,但最初的问题不是如何设置 ContentType 标头,而是如何设置 Content-Type 标头。如果某些 RFC 要求您设置某些标头,则标头名称不区分大小写,但肯定区分连字符。正如我在回答中解释的那样。祝你节日快乐!
0赞 Muzoora Savior 4/1/2022 #19

返回的 API

“不支持的媒体类型”,“状态”:415

将 ContentType 添加到 jsonstring 确实很神奇,这是我的脚本,截至今天,我的脚本 100% 工作

    using (var client = new HttpClient())
            {
                   var endpoint = "api/endpoint;
                    var userName = "xxxxxxxxxx";
                    var passwd = "xxxxxxxxxx";
                    var content = new StringContent(jsonString, Encoding.UTF8, "application/json");

                    var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");

                client.BaseAddress = new Uri("https://example.com/");

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
            
                HttpResponseMessage response = await client.PostAsync(endpoint, content);

                if (response.IsSuccessStatusCode)
                {
                    // Get the URI of the created resource.
                    Uri returnUrl = response.Headers.Location;
                    Console.WriteLine(returnUrl);
                }
                string responseBody = await response.Content.ReadAsStringAsync();
                return responseBody;
        }
1赞 purplecat 1/4/2023 #20

就我的方案而言,第三方 API 正在创建 ,因此我无法使用票数最高的答案来解决问题。而且我不喜欢乱用反思的想法,所以其他答案也不起作用。HttpRequestMessage

取而代之的是,我从这个新类扩展并使用了这个新类作为参数。 包含可以重写的方法,以便在发送对象之前对对象进行更改。如果无法访问 Android Xamarin 库,则可以使用 .AndroidMessageHandlerHttpClientAndroidMessageHandlerSendAsyncHttpRequestMessageHttpMessageHandler

public class XamarinHttpMessageHandler : global::Xamarin.Android.Net.AndroidMessageHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Here I make check that I'm only modifying a specific request
        // and not all of them.
        if (request.RequestUri != null && request.RequestUri.AbsolutePath.EndsWith("download") && request.Content != null)
        {
            request.Content.Headers.Add("Content-Type", "text/plain");
        }
        return base.SendAsync(request, cancellationToken);
    }
}

然后使用:

var client = new HttpClient(new XamarinHttpMessageHandler());
0赞 bkwdesign 2/10/2023 #21

因此,如果你尝试执行 OData 请求,请像这篇 Microsoft 文章一样演示你应该在哪里有一个 Content-Type 标头,如下所示:/$batch

内容类型:多部分/混合;边界=batch_d3bcb804-ee77-4921-9a45-761f98d32029

string headerValue = "multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029";

//You need to set it like thus:
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(headerValue);

同样,您需要的魔力是:MediaTypeHeaderValue.Parse(...)

0赞 CaMiX 7/19/2023 #22

像这样设置内容类型(我的情况是设置“application/vnd.api+json”)对我有用:

var requestBody = new StringContent("{"data": "1"}"), new MediaTypeHeaderValue("application/vnd.api+json"));
var response = await _httpClient.PostAsync(apiUrl, requestBody);
0赞 Alberto Camino 11/17/2023 #23

默认情况下,在 GET 方法中禁止使用 Content-Type 标头,至少在 -NET Framework 实现中是这样。 我使用继承自 HttpClient 类使用的自定义处理程序来解决问题。我重写了 SendAsync 方法,该方法消除了禁止的标头(否则,当您尝试将标头添加到请求时,您将出现异常),并且当请求具有 GET 方法时,我包含标头:

public class GetRequestHandler : HttpClientHandler {

public GetRequestHandler(): base() {
}

protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken) {

    FieldInfo invalidHeadersField = typeof(HttpHeaders).GetField("invalidHeaders", BindingFlags.NonPublic | BindingFlags.Instance) ?? typeof(HttpHeaders).GetField("_invalidHeaders", BindingFlags.NonPublic | BindingFlags.Instance);
    HashSet<string> invalidHeaders = (HashSet<string>)invalidHeadersField.GetValue(request.Headers);

    invalidHeaders.Remove("Content-Type");

    if(request.Method == HttpMethod.Get) {
        request.Headers.Remove("Content-Type");
        request.Headers.Add("Content-Type", "application/json");
    }
    

    return base.SendAsync(request, cancellationToken);

}

}

然后,在 HttpClient 构造函数中,我使用此自定义处理程序:

HttpClient client = new HttpClient(new GetRequestHandler()); 

这样做,现在效果很好:

var response = await client.GetAsync(url);