c# - 呼叫web - 如何為HttpClient請求設置Content-Type標頭?




web api回傳json (5)

.Net試圖強迫你遵守某些標準,即只能在具有內容的請求(例如POSTPUT等)上指定Content-Type標題。 因此,正如其他人所指出的,設置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的建議進行了修改。

我試圖設置一個HttpClient對象的Content-Type頭部,這是我所調用的API所要求的。

我嘗試設置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");
    // ...
}

它允許我添加Accept頭,但是當我嘗試添加Content-Type ,會引發以下異常:

錯誤的標題名稱。 確保請求標頭與HttpRequestMessage一起使用,使用HttpResponseMessage響應標頭,以及使用HttpContent對象的內容標頭。

如何在HttpClient請求中設置Content-Type標頭?


嘗試使用TryAddWithoutValidation

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

如果你不介意小型庫依賴, Flurl.Http [披露:我是作者]使這個超級簡單。 它的PostJsonAsync方法負責序列化內容和設置content-type標題,並且ReceiveJson反序列化響應。 如果需要accept頭文件,則需要自行設置,但Flurl也提供了一個相當乾淨的方法來實現這一點:

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

對於那些沒有看到約翰對卡洛斯解決方案發表評論的人...

req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

關於.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;

而且,正如預期的那樣,我收到了內容為"Cannot send a content-body with this verb-type."的聚合異常"Cannot send a content-body with this verb-type."

但是,如果我使用.NET Core(1.1)做同樣的事情 - 我不會遇到異常。 我的請求非常高興地被我的服務器應用程序回答,並且內容類型被拾取。

我對此感到驚喜,我希望它能幫助別人!





rest