Ger Hayden Ответов: 2

Как получить значение из тела сообщения веб-api?


Мой ASP.NET основные вызовы Post-API Web API 2.2 не получают ничего от тела. Даже при использовании одного поля в теле значение, считанное в POST, равно null. Как мне решить эту проблему?

Что я уже пробовал:

Это текущий код в контроллере API:
[HttpPost("TestUser")]
 public async Task<IActionResult> TestUserAsync(string userName)
 {
     if (ModelState.IsValid)
     {
         return Ok(userName);
     }
     else
     {
         return BadRequest();
     }
 }

Я также попробовал этот код с [FromBody] на месте (тогда ответ от почтальона становится "недопустимым вводом", и метод не вызывается.

Я звоню ему от почтальона:
"http://localhost:5502/LDH/User/TestUser"


Тип контента-Application/Json, и это необработанная строка, передаваемая в качестве тела:
{"userName" : "testUser"}


Некоторые из моих исследований предполагали, что пользовательское ведение журнала промежуточного программного обеспечения может вызвать его, потребляя поток и не сбрасывая его - я использую log4Net. Я не могу найти ничего о том, как сбросить поток, поэтому не могу исключить этого.

Modelstate действителен и не показывает ничего неправильного

2 Ответов

Рейтинг:
2

Richard Deeming

По умолчанию Web API использует следующие правила для привязки параметров:
  • Если параметр имеет "простой" тип, Web API пытается получить значение из URI. Простые типы включают в себя примитивные типы .NET (int, bool, double и т. д.), а также TimeSpan, DateTime, Guid, decimal и string, а также любой тип с преобразователем типов, который может преобразовываться из строки. (Подробнее о преобразователях типов позже.)
  • Для сложных типов Web API пытается прочитать значение из тела сообщения, используя форматер типа носителя.

Ваш параметр-это a string, поэтому привязка модели попытается получить значение из URL-адреса.

Если вы добавите [FromBody] для этого параметра он будет использовать форматер типа носителя для считывания параметра из тела запроса. Для string параметр с помощью application/json тип контента, он ожидает одну строку, заключенную в кавычки:
POST http://localhost:5076/api/values HTTP/1.1
User-Agent: Fiddler
Host: localhost:5076
Content-Type: application/json
Content-Length: 7

"Alice"
Ваше тело не соответствует этому - вы передаете целый объект:
{"userName" : "testUser"}

Рик Страл опубликовал подход к привязке строкового параметра непосредственно к необработанному телу запроса еще в 2013 году, который вы, возможно, сможете адаптировать:
Принятие сырого содержимого тела запроса с помощью ASP.NET Web API - веб-журнал Рика Штрала[^]

В противном случае самым простым решением, вероятно, будет создание класса для представления вашего параметра:
public class TestUserParameters
{
    public string UserName { get; set; }
}
...
[HttpPost("TestUser")]
public async Task<IActionResult> TestUserAsync(TestUserParameters model) { ... }


Ger Hayden

Абсолютно идеально - реальность такова, что я буду проходить сложный класс, а не простой тип, и ваш пример посылает меня в том направлении, в котором я хочу идти.

Ger Hayden

И для пользы будущих читателей это определение ближе к моему реальному решению:

  public class TestSubClass
    {
        public string SampleStr { get; set; }
    }
    public class TestUserParameters
    {
        public string UserName { get; set; }
        public TestSubClass MySubClass {get; set;}
    }
 


а тело почтальона
{"UserName" : "testUser", "MySubClass" : {"SampleStr" : "Mysample"}}


Еще раз спасибо Ричарду за то, что он наставил меня на правильный путь.

Рейтинг:
0

Kornfeld Eliyahu Peter

LMGTFY[^]
И прочитайте первые 5 ссылок...


Ger Hayden

Извините, но это в значительной степени то, что я делал (именно так я узнал, что поток может быть захвачен регистратором). Я быстро просмотрел вашу строку поиска, и 3 из первых 5 обращений имеют дело с несколькими параметрами. Это не сценарий с несколькими параметрами, и обычные исправления, такие как FromBody, были испробованы безрезультатно.

Я попробую заблокировать log4Net и посмотреть, решит ли это проблему.