相关文章推荐
闷骚的弓箭  ·  Android ...·  1 月前    · 
爱健身的灭火器  ·  Python ...·  8 月前    · 
胆小的签字笔  ·  Android ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

How do I pass optional (nullable) [FromBody] parameter in ASP.NET Core (5.0)? If I don't send body in my request I get 415 Unsupported Media Type error. Can this be configured and if so, how to do it on a controller or action, rather than an app level? I presume it has to do something with model validation, but not sure. Thanks.

[HttpGet("[action]")]
public async Task<IActionResult> GetElementsAsync([FromBody] IEnumerable<int> elements = default)
  var result = await dataService.GetData(elements);
  return Ok(result);

EDIT: To clarify:

This is typical scenario and it works normally:

But passing empty body is returning 415 right away without even reaching action: In a project targeting .NET 6.0, I was able to pass a null string parameter in the request by using string? instead of string in the request model. A validation error was thrown if the ? wasn't included. – mpwhitt Jan 20 at 9:52

You can find a solution here:
https://github.com/pranavkm/OptionalBodyBinding

From this issue on github:
https://github.com/dotnet/aspnetcore/issues/6878

And from .net Core 5 you can use this one:

public async Task<IActionResult> GetElementsAsync([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] IEnumerable<int> elements = default)

Also needed (from Pawel experience):

services.AddControllers(options =>{options.AllowEmptyInputInBodyModelBinding = true;})
                Does this solution still requires creating custom filter? I'm on .NET core 5.0 and just adding (EmptyBodyBehavior = EmptyBodyBehavior.Allow) did not change behaviour.
– Pawel
                Sep 13, 2021 at 9:57
                Should be available without custom filter. Chech the global setting. Doc in GitHub and ms doc
– Nicola Biada
                Sep 13, 2021 at 11:20
                I tried adding nullable reference type annotation (IEnumerable<int>? - someone claimed this worked for them: github.com/dotnet/aspnetcore/issues/30690), configure services with services.AddControllers(options =>{options.AllowEmptyInputInBodyModelBinding = true;}) and disabling model validation with services.Configure<ApiBehaviorOptions>(options => {options.SuppressModelStateInvalidFilter = true;}); None of this worked :/
– Pawel
                Sep 13, 2021 at 12:24
                I think [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] expects user to send empty body (as the name would suggest) and not just not sending any body. Difference between message with no body vs message with empty body is like so: curl --location --request POST 'https://localhost:44349/MyController/MyAction' vs curl --location --request POST 'https://localhost:44349/MyController/MyAction' \ --data-raw ''
– Pawel
                Sep 13, 2021 at 15:34

Just add content-type in your request header. Without the content-type:application/json will appear 415 when body is empty.

No changes to your controller. Test in my side is ok.

I created a new asp.net core 5 api project and this is my controller:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace WebApi_net5.Controllers
    public class HomeController : ControllerBase
        [HttpGet("[action]")]
        public string GetElementsAsync([FromBody] IEnumerable<int> elements = default)
            return "value";
                ASP.NET Core team fixed this in .NET 7.0 so setting 'content-type' should no longer be needed. github.com/dotnet/aspnetcore/pull/38092
– Pawel
                Apr 19 at 11:37

With ASP.NET Core 3.1, I could allow nullable optional parameters by implementing Nicola's suggestion:

services.AddControllers(options =>{options.AllowEmptyInputInBodyModelBinding = true;})

I will address some points that were not mentioned here.

  • To get rid of 415 without sending Content-Type you need to create your custom consumer of the Content-Type
  • https://stackoverflow.com/a/65813534/2531209

    But I would say this is an overkill

  • If you pass Content-Type: application/json in your request header you will get "Body cannot be empty" (Tested on .NET 6) and only then @Nicola answer comes in handy.
  • From my tests it looks like modifications to the controller are not needed and only FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow) is enough with nullable type as parameter.

  • Or you can change nothing in your current code and send a header Content-Type: application/json with a body of {}. This will bypasses all of those errors, but this is not the most optimal solutions for public API's
  • As per filters execution flow diagram https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-3.1 ResourceFilters are executed before model binding so you can make a hack and set content-type in order model binder to not crash so you can accept request with no body and content-type header passed from client

    public class MediaTypeResourceFilterAttribute : Attribute, IResourceFilter
            public void OnResourceExecuting(ResourceExecutingContext context)
               context.HttpContext.Request.ContentType ??= "application/json";
            public void OnResourceExecuted(ResourceExecutedContext context)
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.