C# 如何为 HttpClient 请求设置 Content-Type 标头?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10679214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you set the Content-Type header for an HttpClient request?
提问by mynameiscoffey
I'm trying to set the Content-Typeheader of an HttpClientobject as required by an API I am calling.
我正在尝试根据我正在调用的 API 的要求设置对象的Content-Type标头HttpClient。
I tried setting the Content-Typelike below:
我尝试设置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");
// ...
}
It allows me to add the Acceptheader but when I try to add Content-Typeit throws the following exception:
它允许我添加Accept标题,但是当我尝试添加Content-Type它时会引发以下异常:
Misused header name. Make sure request headers are used with
HttpRequestMessage, response headers withHttpResponseMessage, and content headers withHttpContentobjects.
误用的标题名称。确保请求标
HttpRequestMessage头与 一起使用 ,响应标头与 一起使用HttpResponseMessage,内容标头与HttpContent对象一起使用。
How can I set the Content-Typeheader in a HttpClientrequest?
如何Content-Type在HttpClient请求中设置标头?
采纳答案by carlosfigueira
The content type is a header of the content, not of the request, which is why this is failing. AddWithoutValidationas suggested by Robert Levy may work, but you can also set the content type when creating the request content itself (note that the code snippet adds "application/json" in two places-for Accept and Content-Type headers):
内容类型是内容的标头,而不是请求的标头,这就是失败的原因。AddWithoutValidation正如 Robert Levy 所建议的那样可能可行,但您也可以在创建请求内容本身时设置内容类型(请注意,代码片段在两个地方添加了“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);
});
回答by Robert Levy
Call AddWithoutValidationinstead of Add(see this MSDN link).
调用AddWithoutValidation而不是Add(请参阅此 MSDN 链接)。
Alternatively, I'm guessing the API you are using really only requires this for POST or PUT requests (not ordinary GET requests). In that case, when you call HttpClient.PostAsyncand pass in an HttpContent, set this on the Headersproperty of that HttpContentobject.
或者,我猜您使用的 API 实际上只需要 POST 或 PUT 请求(不是普通的 GET 请求)。在这种情况下,当您调用HttpClient.PostAsync并传入 an 时HttpContent,请在该对象的Headers属性上设置 this HttpContent。
回答by archgl
For those who didn't see Johns comment to carlos solution ...
对于那些没有看到约翰对卡洛斯解决方案发表评论的人......
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
回答by Todd Menier
If you don't mind a small library dependency, Flurl.Http[disclosure: I'm the author] makes this uber-simple. Its PostJsonAsyncmethod takes care of both serializing the content and setting the content-typeheader, and ReceiveJsondeserializes the response. If the acceptheader is required you'll need to set that yourself, but Flurl provides a pretty clean way to do that too:
如果你不介意一个小的库依赖,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 uses HttpClient and Json.NET under the hood, and it's a PCL so it'll work on a variety of platforms.
Flurl 在底层使用 HttpClient 和 Json.NET,它是一个 PCL,因此可以在各种平台上运行。
PM> Install-Package Flurl.Http
回答by SharpCoder
try to use TryAddWithoutValidation
尝试使用 TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
回答by erdomke
.Net tries to force you to obey certain standards, namely that the Content-Typeheader can only be specified on requests that have content (e.g. POST, PUT, etc.). Therefore, as others have indicated, the preferred way to set the Content-Typeheader is through the HttpContent.Headers.ContentTypeproperty.
.NET试图迫使你遵守一定的标准,即在Content-Type头只能在有内容(例如,请求指定POST,PUT等等)。因此,正如其他人所指出的,设置Content-Type标题的首选方法是通过HttpContent.Headers.ContentType属性。
With that said, certain APIs (such as the LiquidFiles Api, as of 2016-12-19) requires setting the Content-Typeheader for a GETrequest. .Net will not allow setting this header on the request itself -- even using TryAddWithoutValidation. Furthermore, you cannot specify a Contentfor the request -- even if it is of zero-length. The only way I could seem to get around this was to resort to reflection. The code (in case some else needs it) is
话虽如此,某些 API(例如LiquidFiles Api,截至2016 年 12 月 19日)需要Content-Type为GET请求设置标头。.Net 不允许在请求本身上设置这个标头——即使使用TryAddWithoutValidation. 此外,您不能Content为请求指定 a - 即使它的长度为零。我似乎可以解决这个问题的唯一方法是诉诸反思。代码(以防其他人需要它)是
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");
Edit:
编辑:
As noted in the comments, this field has different names in different versions of the dll. In the source code on GitHub, the field is currently named s_invalidHeaders. The example has been modified to account for this per the suggestion of @David Thompson.
如评论中所述,该字段在不同版本的 dll 中具有不同的名称。在GitHub 上的源代码中,该字段当前名为s_invalidHeaders。该示例已根据@David Thompson 的建议进行了修改以说明这一点。
回答by Jay
Some extra information about .NET Core (after reading erdomke's post about setting a private field to supply the content-type on a request that doesn't have content)...
关于 .NET Core 的一些额外信息(阅读 erdomke 关于设置私有字段以在没有内容的请求上提供内容类型的帖子之后)...
After debugging my code, I can't see the private field to set via reflection - so I thought I'd try to recreate the problem.
调试我的代码后,我看不到要通过反射设置的私有字段 - 所以我想我会尝试重新创建这个问题。
I have tried the following code using .Net 4.6:
我使用 .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;
And, as expected, I get an aggregate exception with the content "Cannot send a content-body with this verb-type."
而且,正如预期的那样,我收到了内容的聚合异常 "Cannot send a content-body with this verb-type."
However, if i do the same thing with .NET Core (1.1) - I don't get an exception.My request was quite happily answered by my server application, and the content-type was picked up.
但是,如果我对 .NET Core (1.1) 做同样的事情 -我不会出现异常。我的服务器应用程序很高兴地回答了我的请求,并选择了内容类型。
I was pleasantly surprised about that, and I hope it helps someone!
我对此感到惊喜,我希望它可以帮助某人!
回答by art24war
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"));
It's all what you need.
这就是你所需要的。
With using Newtonsoft.Json, if you need a content as json string.
使用 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();
}
}
回答by Ziba Leah
Ok, it's not HTTPClient but if u can use it, WebClient is quite easy:
好吧,它不是 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(...);
}
回答by Anshuman Goel
I find it most simple and easy to understand in the following way:
我觉得通过以下方式最简单易懂:
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();

