HttpClient 요청에 대한 Content-Type 헤더를 어떻게 설정합니까?
호출중인 API에 필요한대로 개체 의 Content-Type
헤더 를 설정하려고합니다 HttpClient
.
다음 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
객체 와 함께 사용해야 합니다.
요청에 Content-Type
헤더를 어떻게 설정할 수 HttpClient
있습니까?
콘텐츠 유형은 요청이 아니라 콘텐츠의 헤더이므로 이것이 실패한 것입니다. AddWithoutValidation
Robert Levy가 제안한대로 작동 할 수 있지만 요청 콘텐츠 자체를 만들 때 콘텐츠 유형을 설정할 수도 있습니다 (코드 스 니펫은 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);
});
Johns가 carlos 솔루션에 대한 의견을 보지 못한 사람들을 위해 ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
작은 라이브러리 의존성에 신경 쓰지 않는다면 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
TryAddWithoutValidation을 사용해보십시오
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
닷넷은 즉 것으로, 특정 표준을 준수하도록 강요하려고 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-Type
header for a GET
request. .Net will not allow setting this header on the request itself -- even using TryAddWithoutValidation
. Furthermore, you cannot specify a Content
for 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
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.
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)...
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:
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."
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.
I was pleasantly surprised about that, and I hope it helps someone!
Call AddWithoutValidation
instead of Add
(see this MSDN link).
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.PostAsync
and pass in an HttpContent
, set this on the Headers
property of that HttpContent
object.
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.
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();
}
}
For those who troubled with charset
I had very special case that the service provider didn't accept charset, and they refuse to change the substructure to allow it... Unfortunately HttpClient was setting the header automatically through StringContent, and no matter if you pass null or Encoding.UTF8, it will always set the charset...
Today i was on the edge to change the sub-system; moving from HttpClient to anything else, that something came to my mind..., why not use reflection to empty out the "charset"? ... And before i even try it, i thought of a way, "maybe I can change it after initialization", and that worked.
Here's how you can set the exact "application/json" header without "; charset=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;
Note: The null
value in following won't work, and append "; charset=utf-8"
return new StringContent(jsonRequest, null, "application/json");
Ok, it's not HTTPClient but if u can use it, WebClient is quite easy:
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(...);
}
You can use this it will be work!
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();
You need to do it like this:
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;
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();
'Programing' 카테고리의 다른 글
Java에서 현재 날짜 / 시간을 얻는 방법 (0) | 2020.10.02 |
---|---|
PyPy가 6.3 배 빠르면 CPython을 통해 PyPy를 사용하지 않는 이유는 무엇입니까? (0) | 2020.10.02 |
Java에서 기존 파일에 텍스트를 추가하는 방법 (0) | 2020.10.02 |
Base 64 인코딩은 무엇에 사용됩니까? (0) | 2020.09.30 |
: not () 의사 클래스가 여러 인수를 가질 수 있습니까? (0) | 2020.09.30 |