Метод Post контроллера WebApi2 всегда получает значение null FromBody - PullRequest
0 голосов
/ 12 июля 2020

У меня проблемы с [FromBody] в моем методе POST, всегда имеющим значение null.

Я воспроизвел его с помощью минимального приложения в VS2019:

  • Создать проект ASP. NET Веб-приложение (. NET Framework)
  • Выбрать веб-API

Это создает скелет проекта с классом ValuesController со следующим методом:

public void Post([FromBody] string value)
{
}

Я запускаю этот проект в «IIS Express (Google Chrome)» и просматриваю https://localhost: 44358 / api / values, который отлично работает и срабатывают точки останова в методе Get.

Затем я пытаюсь выполнить POST-данные с помощью cUrl:

curl --header "Content-Type: application/json" --url https://localhost:44358/api/values --data "wibble"

Точка останова достигнута в VS2019, но значение равно нулю (я ожидал "колебания").

I в содержимом запроса можно увидеть, что длина равна 6, и это меняется в зависимости от длины строки, которую я передаю в данные, но вызовы для ее чтения возвращают пустые строки или байт [] нулей.

this.Request.Content.ReadAsStringAsync().Result     ""
this.Request.Content.Headers.ContentType            {application/json}
this.Request.Content.Headers.ContentLength          6

Попытка выполнить POST из другого C# приложения с помощью HttpClient также дает те же результаты.

* 1 026 * Что мне не хватает? Тот факт, что проблема возникает в приложении-скелете по умолчанию, и все не жалуются на это, предполагает, что это должно быть что-то очевидное, но ...

ОБНОВЛЕНИЕ

Я вижу ту же проблему в Fiddler, но заставил ее работать с HttpClient, используя:

client.PostAsync<string>(url, "wibble", new JsonMediaTypeFormatter()).Result;

Но следующее не работает (получено как null):

client.PostAsync(url, new StringContent("wibble", Encoding.UTF8), new JsonMediaTypeFormatter()).Result;

1 Ответ

0 голосов
/ 15 июля 2020

Изменение сгенерированного кода с:

public void Post([FromBody] string value) { ... }

на:

public void Post([FromBody] MyClass value) { ... }

Теперь работает с использованием стандартного cUrl / Fiddler / Javascript / et c POST.

Итак, я предполагаю, что проблема заключается в попытке автоматически преобразовать строку в объект, что объясняет, почему у большого числа людей нет этой проблемы.

Если вы действительно хотите отправить текст POST, автоматически сгенерированный контроллер (похоже, он должен делать то, что вы хотите) не работает.

Чтобы обойти это, измените метод Post на:

public void Post()
{
    string value = Request.Content.ReadAsStringAsync().Result;
    ...
}

Отсутствие [FromBody] теперь означает, что Request.Content.ReadAsStringAsync() возвращает содержимое, как ожидалось.

В итоге:

[Route("api/values/obj")]
public void Post([FromBody] MyObject value) /* OK */
{
    ...
}

[Route("api/values/str")]
public void Post([FromBody] string value) /* FAIL */
{
    ...
}

[Route("api/values/str2")]
public void Post() /* OK */
{
    string value = Request.Content.ReadAsStringAsync().Result;
    ...
}

Имеет следующие результаты из cUrl:

curl "http://localhost:59801/api/Values/obj"  --header "Content-Type: application/json" --data "{id:1, name:'Andy'}"

OK

curl "http://localhost:59801/api/Values/str2" --header "Content-Type: text/plain"       --data "wibble"

ОК

curl "http://localhost:59801/api/Values/str2" --header "Content-Type: application/json" --data "wobble"

ОК

curl "http://localhost:59801/api/Values/str"  --header "Content-Type: text/plain"       --data "wibble"

Ошибка. Исключение «Тип мультимедиа объекта запроса« text / plain »не поддерживается для этого ресурса.»

curl "http://localhost:59801/api/Values/str"  --header "Content-Type: application/json" --data "wobble"

Ошибка. Значение равно null.

...