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.