Skip to main content

Fixed: "Body was inferred but the method does not allow inferred body parameters" in a Minimal API

· 6 min read
Jagdish Kumawat
Founder @ Dewiride

After I added one small GET endpoint, every request to my minimal API answered 500, health checks included. The log said Body was inferred but the method does not allow inferred body parameters. The endpoint took a record as a parameter, and ASP.NET Core assumes that comes from the JSON body, which GET doesn't get. [AsParameters] tells it to read the query string instead.

What I Was Doing​

In a .NET 10 minimal API, I added a GET endpoint that takes a record, the same way a POST endpoint does:

src/Dewiride.Inventory.Api/DemoEndpoints.cs (excerpt)
public sealed record PlainProductRequest(string Sku, decimal UnitPrice, int ReorderLevel);

d.MapGet("/plain-record", (PlainProductRequest request) => Results.Ok(request));

It built with no errors, and the API started. Then I sent a request to a different endpoint, one that had always worked:

Request
GET http://localhost:5190/api/v1/categories

What I Expected​

200 OK. I hadn't touched that endpoint.

What I Got​

A 500, and the same for every address I tried:

API log (the lines that matter)
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Body was inferred but the method does not allow inferred body parameters.
Below is the list of parameters that we found:

Parameter | Source
---------------------------------------------------------------------------------
request | Body (Inferred)


Did you mean to register the "Body (Inferred)" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?

A terminal with the API log showing InvalidOperationException: Body was inferred but the method does not allow inferred body parameters, with a table listing request as Body (Inferred).

What I Checked​

Which endpoint caused it. The table names one parameter, request, with the source Body (Inferred). It doesn't say which endpoint, but only one endpoint was new, and it was the only GET with a record parameter.

Why it reads from the body. ASP.NET Core's parameter binding page says: "Binding sources can be explicit or inferred based on HTTP method and parameter type." A class or record that isn't a service is assumed to be the JSON body. For GET, that assumption isn't allowed, because a GET isn't expected to have a body. That's the "method does not allow" in the message.

Why every endpoint fails. All the endpoints are built together when the first request needs them, so one that can't be built stops the whole lot. The API starts cleanly and fails on its first request, which makes it look like a much bigger problem.

Why It Happens​

For a record parameter with no attribute, ASP.NET Core looks for a registered service, and then falls back to the request body. On GET, DELETE and similar methods that don't normally carry a body, that fallback is an error. The message offers the two ways out: "Did you mean to register the "Body (Inferred)" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?" For a GET, neither of those is what you want, and there's a third way it doesn't mention.

The Fix​

For values in the query string, which is what a GET should use, add [AsParameters], so each property of the record binds on its own:

src/Dewiride.Inventory.Api/DemoEndpoints.cs (excerpt)
d.MapGet("/asparameters-record", ([AsParameters] PlainProductRequest request) => Results.Ok(request));

If the data really belongs in a body, make it a POST:

src/Dewiride.Inventory.Api/DemoEndpoints.cs (excerpt)
d.MapPost("/plain-record", (PlainProductRequest request) => Results.Ok(request));

After the Fix​

Every endpoint works again, and the new one reads the query string:

Request
GET http://localhost:5190/demo/asparameters-record?sku=CBL-1&unitPrice=2.50&reorderLevel=3
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"sku": "CBL-1",
"unitPrice": 2.50,
"reorderLevel": 3
}

A terminal with a GET request with sku, unitPrice and reorderLevel in the query string, answered with 200 OK and those values, and the other endpoints answering normally again.

Common Mistakes​

MistakeWhat happensDo this instead
Looking for the bug in the endpoint you calledEvery endpoint fails because of oneRead the table, and check the newest endpoint
Adding [FromBody] to a GETIt compiles, and clients must send a body on GET, which many can'tUse [AsParameters]
Adding [FromQuery] to the record itselfIt needs a TryParse for that typeUse [AsParameters]
Only testing the new endpoint on its ownYou see the error, but not that it took down the restRun a known-good request too

Troubleshooting​

SymptomLikely causeFix
Body was inferred but the method does not allow inferred body parametersA record or class parameter on GET, DELETE or similarUse [AsParameters]
A parameter is listed as UNKNOWNA service that isn't registeredSee that post
Failure to infer one or more parameters naming two body parametersTwo records on a POSTKeep one body, and mark the others
Every address answers 500 right after a code changeOne endpoint can't be builtRead the log's parameter table

FAQ​

Why doesn't this fail when the app starts?​

Endpoints are built the first time they're needed, not while starting. A request to anything triggers it.

Can a GET have a body?​

HTTP doesn't forbid it, but many clients and proxies drop it, so ASP.NET Core won't assume one. Using the query string avoids the problem.

Conclusion​

"Body was inferred but the method does not allow inferred body parameters" means a GET or DELETE endpoint has a record or class parameter with no attribute, and ASP.NET Core assumed it was a JSON body. It takes down every endpoint until it's fixed. Use [AsParameters] for query values, or make it a POST.

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.