InvalidOperationException: Misused header name, 'Content-Type'. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
is thrown when you add Content-Type to HttpClient.DefaultRequestHeaders.
In .NET, Content-Type is a header of the body, so it goes on the
HttpContent you send, not on the client or the request.
Delete the DefaultRequestHeaders.Add("Content-Type", ...) line and pass the media
type when you create the content: new StringContent(json, Encoding.UTF8, "application/json").
The error
PS ...\Cli> dotnet run --no-build -- misused
Unhandled exception. System.InvalidOperationException: Misused header name, 'Content-Type'. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
at System.Net.Http.Headers.HttpHeaders.GetHeaderDescriptor(String name)
at System.Net.Http.Headers.HttpHeaders.Add(String name, String value)
at Program.<Main>$(String[] args) in ...\Cli\Program.cs:line 24
at Program.<Main>(String[] args)
The line that threw:
using var http = new HttpClient { BaseAddress = new Uri("http://127.0.0.1:15801/api/v1/") };
http.DefaultRequestHeaders.Add("Content-Type", "application/json");
Why it happens
System.Net.Http keeps headers in three separate collections: request headers
on HttpRequestMessage (and the client's DefaultRequestHeaders),
response headers on HttpResponseMessage, and content headers on
HttpContent. Content-Type describes the body, so it belongs to the
content collection. Adding it to a request-header collection with Add throws at
that line, before any request is made: the stack trace ends in
HttpHeaders.Add, not in a send method.
Moving the header from the client to an HttpRequestMessage does not help, and
TryAddWithoutValidation does not get around it either. A second run tried both
on a request message:
using var req = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:15801/api/v1/patients");
Console.WriteLine("TryAddWithoutValidation returned " + req.Headers.TryAddWithoutValidation("Content-Type", "application/json"));
req.Headers.Add("Content-Type", "application/json");
PS ...\Cli> dotnet run --no-build -- misused-req
TryAddWithoutValidation returned False
Unhandled exception. System.InvalidOperationException: Misused header name, 'Content-Type'. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
at System.Net.Http.Headers.HttpHeaders.GetHeaderDescriptor(String name)
at System.Net.Http.Headers.HttpHeaders.Add(String name, String value)
...
The try method returned False without throwing, which is easy to miss: the
header is silently not added. The plain Add on the request message threw the
same exception as on the client.
The fix
using var http = new HttpClient { BaseAddress = new Uri("http://127.0.0.1:15801/api/v1/") };
using var content = new StringContent("{\"name\":\"Maria Garcia\"}", System.Text.Encoding.UTF8, "application/json");
Console.WriteLine("Content-Type: " + content.Headers.ContentType);
using var resp = await http.PostAsync("patients", content);
Console.WriteLine((int)resp.StatusCode + " " + resp.RequestMessage!.RequestUri);
PS ...\Cli> dotnet run --no-build -- misused-fixed
Content-Type: application/json; charset=utf-8
200 http://127.0.0.1:15801/api/v1/patients
The content carries the header, with a charset=utf-8 parameter added from the
encoding argument, and the POST to the test server's route answered 200. The client
itself needs no header setup for this: the BaseAddress stays on the client,
the body type travels with each body.
How it was reproduced
A console app (dotnet new console, no packages) on .NET SDK 10.0.403 created an
HttpClient and called DefaultRequestHeaders.Add("Content-Type",
"application/json"). The fixed version posted to a minimal API
(dotnet new web) running on http://127.0.0.1:15801 with a POST
route at /api/v1/patients. The request-message run needed no server, because
the exception came from the Add call before anything was sent.
Frequently asked
- How do I set Content-Type on HttpClient in C#?
- Set it on the content, not the client: new StringContent(json, Encoding.UTF8, "application/json"). The content then carries Content-Type: application/json; charset=utf-8.
- Why does DefaultRequestHeaders.Add Content-Type throw?
- Content-Type is a content header in System.Net.Http. Request-header collections such as DefaultRequestHeaders refuse it with the Misused header name exception at the Add call.
- Is the Misused header name error thrown when the request is sent?
- No. In the test it was thrown by the Add call itself, and the stack trace ended in HttpHeaders.Add, before any send method ran.
More decoded errors in the Fixes category. If the same client then fails on a relative path, see An invalid request URI was provided.