Skip to main content

Fixed: "415 Unsupported Media Type" from a POST to an ASP.NET Core Minimal API

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

A POST with perfectly good JSON came back as 415 Unsupported Media Type, and the API's log had nothing to say about it. The JSON wasn't the problem: the request never said it was JSON. curl labels a -d body as a web form unless you tell it otherwise, and a minimal API endpoint that expects JSON won't touch that.

What I Was Doing​

A .NET 10 minimal API has an endpoint that takes a JSON body, through a record parameter:

src/Dewiride.Inventory.Api/Features/Categories/CategoryEndpoints.cs (excerpt)
private static async Task<Results<Created<CategoryResponse>, ProblemHttpResult>> CreateAsync(
CategoryRequest request,

I sent it a JSON body with curl:

Terminal
curl -i -X POST http://localhost:5190/api/v1/categories -d '{"name":"Form"}'

What I Expected​

201 Created.

What I Got​

Response
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/problem+json

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.16",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "00-522930cbe0a99ef7a908259655babf4d-3e463430e46c094b-00"
}

The API's normal log stayed empty for this request.

A terminal with a curl POST with a JSON body and no Content-Type header, answered with 415 Unsupported Media Type as problem details.

What I Checked​

What the API saw. To see more, I ran the API with the Microsoft.AspNetCore log level at Debug, passing it on the command line:

Terminal
dotnet run --project src/Dewiride.Inventory.Api -- --Logging:LogLevel:Microsoft.AspNetCore=Debug
API log (the lines that matter)
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5190/api/v1/categories - application/x-www-form-urlencoded 15
dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1]
Request matched endpoint '415 HTTP Unsupported Media Type'

There it is: application/x-www-form-urlencoded. That's what curl's -d sends by default. And routing itself chose the 415, without running the endpoint, which is why nothing else was logged.

What the documentation says. The error handling page mentions the status for "unsupported request content types" on JSON body binding, and the parameter binding page lists "Body (as JSON)" as a binding source. So the endpoint accepts JSON, and the request said it was something else.

Why It Happens​

Content-Type tells the server how to read the body. A record parameter makes ASP.NET Core expect JSON, and it goes by that header, not by what the bytes look like. A body labelled as a web form isn't accepted, even if its text happens to be valid JSON.

The Fix​

Send the header. In curl:

Terminal
curl -i -X POST http://localhost:5190/api/v1/categories -H "Content-Type: application/json" -d '{"name":"With header"}'

In a .http file, put it right under the request line, with a blank line before the body:

src/Dewiride.Inventory.Api/Dewiride.Inventory.Api.http (excerpt)
POST {{Dewiride.Inventory.Api_HostAddress}}/api/v1/categories
Content-Type: application/json

{
"name": "With header"
}

After the Fix​

Response
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Location: /api/v1/categories/502

{
"id": 502,
"name": "With header",
"createdAtUtc": "2026-11-04T11:43:36.60438Z"
}

A terminal with the same curl POST with a Content-Type: application/json header, answered with 201 Created and the new category.

Common Mistakes​

MistakeWhat happensDo this instead
Assuming curl's -d means JSONIt sends a form typeAdd the header
Changing the endpoint to read the raw bodyYou lose binding and validationFix the client
Forgetting the blank line in a .http fileThe body is read as more headersPut one blank line before the body
Adding [FromForm] to make it passThe endpoint no longer reads JSONSend JSON with the right header

Troubleshooting​

SymptomLikely causeFix
415 Unsupported Media Type with no error in the logNo Content-Type: application/jsonAdd it
400 Bad Request after adding the headerThe JSON itself is brokenSee the bad request post
415 from a browser formForms send a form typeSend JSON with fetch, or accept forms
415 with text/plainA client library's defaultSet the content type in the client

FAQ​

Why doesn't ASP.NET Core look at the body and guess?​

Because the header is what HTTP defines for this. Guessing would make a client's mistake look like it worked, until the day it didn't.

Does curl's --json flag help?​

Yes: --json sets the header for you, in curl 7.82 and newer. Older copies of curl don't have it.

Conclusion​

415 Unsupported Media Type from a minimal API POST means the request didn't say its body is JSON. curl's -d sends application/x-www-form-urlencoded, and routing answers 415 before your code runs, so the log stays quiet. Add Content-Type: application/json.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.