Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp Core 3 - How to allow nullable [FromBody] object in controller method

Let's say I have a simple controller with one POST method that accepts an object from its body. However, the presence of this object should be optional in the HTTP request body. I tried to implement this behavior with the following code

public class User
{
    public string Name { get; set; }
}

[ApiController]
[Route("[controller]")]
public class GreetingController : ControllerBase
{
    [HttpPost]
    public string SayHello([FromBody] User user = null)
    {
        return "Hello " + user?.Name;
    }
}

If I make a request with an object in the body, everything works fine. But with this configuration, it is unable to make a POST request with empty body. If I create a request without Content-Type header (as there is actually no content), I get the following error:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
    "title": "Unsupported Media Type",
    "status": 415,
    "traceId": "|192e45d5-4bc216316f8d3966."
}

if the Content-Type header has value application/json then the response looks like this:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|192e45d6-4bc216316f8d3966.",
    "errors": {
        "": [
            "A non-empty request body is required."
        ]
    }
}

So, how to make the object optional in the request body? It is quite common problem and I am curious if there is a simple solution for that in ASP Core 3. I don't want to read the object from Request stream and deserialize it on my own.

like image 787
Mayo Avatar asked Mar 06 '26 06:03

Mayo


2 Answers

There is now an easier way (since 5.0-preview7)

You can now achieve this per action method, by configuring a FromBodyAttribute property named EmptyBodyBehavior

Demonstration:

public IActionResult Post([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] MyModel model)

Thanks to LouraQ's comment, which guided me towards the above answer on github

like image 60
Daniel Avatar answered Mar 07 '26 19:03

Daniel


Right now, the only way is via a global option, MvcOptions.AllowEmptyInputInBodyModelBinding. It defaults to false, so you just need to do:

services.AddControllers(o =>
{
    o.AllowEmptyInputInBodyModelBinding = true;
});
like image 35
Chris Pratt Avatar answered Mar 07 '26 20:03

Chris Pratt