我试图设置一个HttpClient对象的Content-Type头作为我调用的API所要求的。

我试着像下面这样设置内容类型:

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");
    // ...
}

它允许我添加Accept头,但当我尝试添加Content-Type时,它会抛出以下异常:

误用头名称。确保请求头与一起使用 HttpRequestMessage,带有HttpResponseMessage的响应头,以及 内容头与HttpContent对象。

如何在HttpClient请求中设置内容类型报头?


当前回答

我发现下面的方法最简单易懂:

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();

其他回答

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;
        }

内容类型是内容的头,而不是请求的头,这就是失败的原因。Robert Levy建议的AddWithoutValidation可以工作,但是你也可以在创建请求内容本身时设置内容类型(注意,代码片段在两个地方添加了application/json - Accept和content - type头):

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);
      });

好吧,它不是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(...);
 }

你可以用这个,它会工作!

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();

. net试图强迫你遵守某些标准,即content - type头只能在有内容的请求上指定(例如POST, PUT等)。因此,正如其他人指出的那样,设置Content-Type报头的首选方法是通过HttpContent.Headers.ContentType属性。

话虽如此,某些Api(如截至2016-12-19的LiquidFiles Api)需要为GET请求设置Content-Type报头,. net不允许在请求本身设置此报头——即使使用TryAddWithoutValidation。此外,您不能为请求指定Content——即使它的长度为零。我唯一能避开这个问题的方法似乎就是诉诸于反思。代码(以防其他人需要它)是

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的源代码中,该字段当前命名为s_invalidHeaders。这个例子已经根据@David Thompson的建议进行了修改。