Как передать null в теле на конечную точку в пределах asp. net core 3.1 - PullRequest
3 голосов
/ 19 января 2020

У меня есть следующее действие в asp. net ядре 3.1 контроллера

[ApiController]
[Route("example")]
public class MyExampleController : ControllerBase
{
    [HttpPost("{id}/value")]
    public async Task<IActionResult> Post(string id, [FromBody] int? value)
      => Task.FromResult(Ok());
}

Это прекрасно работает, если я публикую значение тела int (например: 1, 2, et c ...)

Однако я не могу найти способ получить значение null, переданное внутрь.

Если я передаю пустое тело или null body Возвращается код состояния 400 с возвращенным сообщением проверки A non-empty request body is required..

Я также пытался изменить параметр value на необязательный аргумент со значением по умолчанию null:

public async Task<IActionResult> Post(string id, [FromBody] int? value = null)

Как передать null этому действию?

Ответы [ 3 ]

2 голосов
/ 21 января 2020

Наконец-то понял это, большое спасибо @Nkosi и @KirkLarkin, которые помогли найти ошибку.

Внутри Startup.cs при настройке контроллеров в контейнер нам просто нужно изменить параметры по умолчанию mvc на AllowEmptyInputInBodyModelBinding

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(x => x.AllowEmptyInputInBodyModelBinding = true);
}

Таким образом, мы можем передать null в тело сообщения, и оно прекрасно работает. Он также по-прежнему применяет обычную проверку модели через атрибуты без необходимости вручную проверять ModelState:

public async Task<IActionResult> Post(string id,
        [FromBody][Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than 1")]
        int? value = null)
2 голосов
/ 20 января 2020

Ссылка Автоматизация c Ответы HTTP 400

Атрибут [ApiController] позволяет ошибкам проверки модели автоматически инициировать ответ HTTP 400

Это объяснило бы возвращенный ответ.

Удалите [ApiController], чтобы разрешить недопустимому запросу все еще выполнять действие контроллера, а также если дополнительные функции наличия этого атрибута не являются критическими для текущего контроллера.

Однако потребуется, чтобы требуемый элемент был применен вручную

[Route("example")]
public class MyExampleController : ControllerBase {
    [HttpPost("{id}/value")]
    public async Task<IActionResult> Post(string id, [FromBody] int? value) {

        if (!ModelState.IsValid) {

            //...

            return BadRequest(ModelState);
        }

        //...

        return Ok();
    }
}
0 голосов
/ 20 января 2020

Кажется, это как-то связано с тем, как одно значение проводится через JSON. Он ожидает значение, а null просто создает пустое тело запроса. Вам следует подумать об определении класса, подобного этому

    public class MyInt{
        public int Value { get; set; }
        public bool IsNull { get; set; }
    }

    [ApiController]
    [Route("example")]
    public class MyExampleController : ControllerBase
    {
        [HttpPost("{id}/value")]
        public IActionResult Post(string id, [FromBody]MyInt value)
        {
            if(value.IsNull){

            }
            else{

            }
            return Ok();
        }
    }

Другими словами, когда вы публикуете POST, вы публикуете не просто значение по умолчанию. Вы могли бы сделать это другим способом, как это

[HttpPost("{id}/value")]
public IActionResult Post(string id, [FromBody]int value)...
[HttpGet("{id}/value")]
public IActionResult Get(string id)...//use the default value here
...