How do you set the Content-Type header for an HttpClient request?
Solution 1
The content type is a header of the content, not of the request, which is why this is failing. AddWithoutValidation
as 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):
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);
});
Solution 2
For those who didn't see Johns comment to carlos solution ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
Solution 3
If you don't mind a small library dependency, Flurl.Http [disclosure: I'm the author] makes this uber-simple. Its PostJsonAsync
method takes care of both serializing the content and setting the content-type
header, and ReceiveJson
deserializes the response. If the accept
header is required you'll need to set that yourself, but Flurl provides a pretty clean way to do that too:
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.
PM> Install-Package Flurl.Http
Solution 4
try to use TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
Solution 5
.Net tries to force you to obey certain standards, namely that the Content-Type
header 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-Type
header is through the HttpContent.Headers.ContentType
property.
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.
Comments
-
mynameiscoffey almost 2 years
I'm trying to set the
Content-Type
header of anHttpClient
object as required by an API I am calling.I tried setting the
Content-Type
like below: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
Accept
header but when I try to addContent-Type
it throws the following exception:Misused header name. Make sure request headers are used with
HttpRequestMessage
, response headers withHttpResponseMessage
, and content headers withHttpContent
objects.How can I set the
Content-Type
header in aHttpClient
request?-
jiping-s over 5 yearsYou could follow how HttpWebRequest in .NET Core does it (it uses HttpClient internally), see github.com/dotnet/corefx/blob/master/src/System.Net.Requests/… "SendRequest" method
-
-
dhara tcrails over 11 yearsAlternatively,
Response.Content.Headers
will work most of the time. -
jerhewet over 9 years@AshishJain Most of the SO answers I've seen involving
Response.Content.Headers
for the ASP.Net Web API haven't worked either, but you can easily set it usingHttpContext.Current.Response.ContentType
if you need to. -
Ashish-BeJovial over 9 years@jerhewet i used in following way which worked for me. var content = new StringContent(data, Encoding.UTF8, "application/json");
-
Julian Reschke almost 9 yearsContent-Type is a property of an HTTP message with payload; it has nothing to do with request vs response.
-
Matteo Defanti over 8 yearsIt made difference downloading a pdf. From the phone it tried to download an HTML. After converting the extension the file was normally encoded.
-
John Meyer almost 8 yearsI had to throw .ToString() on the end, but yes this worked for a WCF service implementation.
-
Bill Noel over 7 yearsInteresting. I tried creating a new StringContent with the three parameters and it didn't work. I then manually: request.Content.Headers.Remove("Content-Type") and then: request.Content.Headers.Add("Content-Type", "application/query+json") and it worked. Odd.
-
prem over 7 yearsNot working with .Net Framework version 4.0, System.Net.Http version 2.2.29.0 but working with 2.0.0.0
-
Vlado Pandžić about 7 yearsHow to send if content is application/x-www-form-urlencoded?
-
David Thompson about 7 yearsThis field is now s_invalidHeaders so using the following ensures compatibility: 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);
-
Mahmoud Samy about 7 yearsStringContent should be dispossed
-
Jay almost 7 yearsAdded an answer related to this for .NET Core 1.1
-
Halter almost 7 yearsWhat is the "relativeAddress" bit?
-
Gerard ONeill almost 7 yearsThanks, Jay -- Not using core, and will use erdomke's answer. I appreciate knowing that all reasonable avenues have been tried :).
-
Tarek El-Mallah over 6 yearsnot working .net 4 ({"Cannot send a content-body with this verb-type."})
-
Jay over 6 years@TarekEl-Mallah Yes - please read the comments in my answer. The whole point of my post was to illustrate that it doesn't work in .NET 4, but it does work in .NET core (they are not the same thing). You will have to see erdomeke's answer to the OP's question to be able to hack it to work in .NET 4.
-
Tarek El-Mallah over 6 yearsI applied that fix, and there is a major error happened, if there is something wrong with the HTTP request, the whole further requests fail, any network traffic will fail in the whole iis service. My advice, do not use that at all and search for alternative solution.
-
erdomke over 6 yearsI am confused on how this code would cause the catastrophic errors you describe. Can you provide more details on your use case and the errors you are receiving?
-
Martin Lietz over 6 yearsnot working gives me a 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
-
Martin Lietz over 6 yearsnot working gives me a 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
-
urbanhusky over 6 yearsHttpClient should be reused (static) and used as such (do not set base address, default request headers etc.)
-
BradLaney almost 6 yearsThis is bad. You should re-use HttpClient. DefaultRequestHeaders are only supposed to be used if you're using the HttpClient for many different related issues. HttpClient's are supposed to be closely related to instantiated as singletons. Aka re-used.
-
Alejandro almost 6 yearsCan you give a small explanation of what it does?
-
KansaiRobot almost 6 yearsAddWithoutValidation does not exist
-
Randall Flagg over 5 yearsThe first line fails with CS0144: "Cannot create an instance of the abstract class or interface 'HttpContent'"
-
AlfeG over 5 yearsWow. Even more wow, that Asp.net WebApi GET methods require Content-Type to be explicitly specified =(
-
mmix over 5 yearsHolly molly, I cannot believe I have to resort to this. Since when do the .NET framework devs it needy to hold my hand in what I can add to Http header section? Abominable.
-
art24war over 5 yearsand then
HttpMessageHandler handler = new WebRequestHandler(); HttpResponseMessage result; using (var client = (new HttpClient(handler, true))) { result = client.PostAsync(fullUri, content).Result; }
-
granadaCoder over 5 yearsI will eventually figure out what object type "req" is ... by trial and error........BUT it would be great to show that. Thank you for your consideration.
-
granadaCoder over 5 yearsSystem.Net.Http.HttpRequestMessage from "microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Http.dll" is where I found it.
-
granadaCoder over 5 yearsThose of you reporting "working" or "not working", HttpClient is a very ambiguous object these days. Please report the fullname(space) and .dll assembly it is coming from.
-
I Stand With Israel over 5 yearsJust so folks know, using MediaTypeHeaderValue will return an error if attempting to set the charset, like so;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml; charset=utf-8");
-
joedotnot over 5 yearsJohns comment to Carlo's solution said Response.Content.Headers, but you are using req.Content.Headers ? i.e. Request vs Response ?
-
ps2goat about 5 yearsthe
Misused header name
error is confirmed with dotnet core 2.2. I had to use @carlosfigueira's answer stackoverflow.com/a/10679340/2084315. -
nldev almost 5 yearsI was experiencing the same issue. Your solution seems to be the only one working for me (Calling an external API requiring Content-Type on get requests.) Thanks!
-
GDroid almost 5 yearsAwesome hack. Works for me, however, first time it does't apply the JSON header, but all subsequent calls it does. Anyone had similar behavior? I did work around it but any good hack around it?
-
Tim Davis over 4 yearsrelativeAddress is the url
-
BVernon about 4 yearsI was getting errors trying to post with "application/vnd.api+json". Was just about to give up when I saw this and it fixed my issue.
-
DesertFoxAZ about 4 yearsstringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); also works
-
DesertFoxAZ about 4 yearsI've noticed that if I use this in my API which calls a 3rd-party API the first request is successful but subsequent ones fail and I can't get it working again unless I restart IIS.
-
phoenixstudio over 3 yearsplease edit your question, try to explain the issue and your solition (without imojis)
-
danyloid over 3 yearsThanks for posting it, it is quite unfortunate the validation is enforced to this extent
-
martinp999 over 3 yearsTo be clear, System.Net.Http has provided a poor implementation here. Content-Type is an HTTP request header and an implementation that suggests otherwise is misleading and confusing. However, as you are using dotnet, you have to live with it. (developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type).
-
yoel halb about 3 yearsAlthough this is a great answer, it no longer works in newer .Net versions, see my answer at stackoverflow.com/a/66449794/640195 for an updated answer
-
ProgrammingLlama about 3 yearsWhy is all this reflection necessary? It's the content object that dictates Content-Type, and you can add a content object on GET requests as well as POST, PUT, etc. If you don't have a content object (body) then Content-Type is an irrelevant header.
-
yoel halb about 3 years@John There are frameworks including Microsoft own frameworks that require the header even for a Get and even when there is no Content, don't ask me why.. and why their client removes it when their server expects it...
-
yoel halb about 3 yearsI guess there is a fight between the Microsoft teams and we are the monkeys in the middle...
-
ProgrammingLlama about 3 yearsUnless the Content-Length header presents a problem, isn't it better just to create a derived
HttpContent
object that allows you to specify the header rather than doing all this reflection? -
Simple about 3 years@carlosfigueira According to Microsoft Documentation regarding the
DefaultRequestHeaders
it says: "Headers set on this property don't need to be set on request messages again." So you should not addContent-Type
again in theHttpRequestMessage
, justStringContent(String, Encoding)
should be enough. -
codeMonkey almost 3 yearsThis only works with .NET Core, not .NET Framework.
-
kennydust over 2 years@billnoel's answer should be the correct answer
-
Craig Brown over 2 yearsFor JSON content, as of .NET 5 you can do:
requestMessage.Content = JsonContent.Create(new {Name = "John Doe", Age = 33});
and the Content-Type is set automatically. -
Garr Godfrey over 2 yearsproblem I'm running into is that PostAsJsonAsync doesn't set the
Content-type
header!! -
nuander about 2 yearsThe problem with using this is that it breaks all the other API calls that didn't have this problem. I think because of the BindingFlags.Static which is required to make this work.