Передача объекта List и int в веб-api - PullRequest
1 голос
/ 04 августа 2020

У меня есть проект ядра веб-API, в котором если я отправлю только параметр списка, API получит значения, однако, если я отправлю оба параметра, которые ищет контроллер, оба параметра будут отображаться как null Мой контроллер:

[HttpPost]
[Route("/jobApi/RunBD")]
public int RunBDReport([FromBody]int month, [FromBody] IEnumerable<ClientModel> clients)
{
    billingDetailCycle objBillDetail = new billingDetailCycle();
    if (ModelState.IsValid)
    {
       return objBillDetail.Run(clients.ToList(), month);
    }
    else
    {
        return 500;
    }
}

ClientModel:

public class ClientModel
{
    public string BlockOfBus { get; set; }
    public string ClientId { get; set; }
    public string Location { get; set; }
    public string SuppressSsn { get; set; }
}

Отправляемый мной запрос:

{"month":7,
"ClientModel":[{"blockOfBus":"XXX",
"clientId":"123456",
"location":"",
"suppressSsn":"N"}]}

Это приводит к тому, что оба параметра воспринимаются контроллером как нулевые. , однако, если я отправлю свой запрос следующим образом:

[{"blockOfBus":"XXX",
"clientId":"123456",
"location":"",
"suppressSsn":"N"}]

Тогда контроллер сможет увидеть объект списка, который я отправляю (однако он, очевидно, возвращает 500, поскольку модель недействительна)

Ответы [ 5 ]

2 голосов
/ 04 августа 2020

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

Не применяйте [FromBody] к более чем одному параметру для каждого метода действия. После того, как поток запроса считывается модулем форматирования ввода, он больше не доступен для повторного чтения для привязки других [FromBody] параметров.

Ссылка Привязка модели в ASP. NET Core

Создайте одну модель, которая соответствует ожидаемым данным.

public class DbReport {
    public int month { get; set; }
    public ClientModel[] ClientModel { get; set; }
}

И обновите действие соответствующим образом

[HttpPost]
[Route("/jobApi/RunBD")]
public int RunBDReport([FromBody]DbReport report) {
    billingDetailCycle objBillDetail = new billingDetailCycle();
    if (ModelState.IsValid) {
       return objBillDetail.Run(report.ClientModel.ToList(), report.month);
    } else {
        return 500;
    }
}
1 голос
/ 04 августа 2020

Может быть изменен только один параметр с атрибутом [FromBody]. Таким образом, вам нужно либо изменить свой метод следующим образом:

[Route("/jobApi/RunBD/{month}")]
public int RunBDReport(int month, [FromBody] IEnumerable<ClientModel> clients)

Затем сделайте запрос следующим образом:

url :/jobApi/RunBD/7
body :
[{"blockOfBus":"XXX",
"clientId":"123456",
"location":"",
"suppressSsn":"N"}]

Или измените свой метод и модель следующим образом:

public class BdPayload{
public int Month {get; set;}
public IEnumerable<ClientModel> ClientModel {get;set;}
}

[Route("/jobApi/RunBD")]
public int RunBDReport( [FromBody] BdPayload model)

, а затем вы можете использовать тело второго запроса.

0 голосов
/ 04 августа 2020

Есть несколько простых правил, которые помогут вам справиться с подобными проблемами при попытке передать данные в конечную точку веб-API. Это правила по умолчанию, на основе которых происходит привязка параметров. На основе этих правил вам необходимо применить такие атрибуты, как [FromBody] и [FromUri]

  • GET. Вызов метода принимает как примитивные, так и сложные типы как часть строки запроса
  • POST по умолчанию принимает параметр примитивного типа в строке запроса, а сложный тип должен передаваться как часть тела запроса.
  • PUT и PATCH следуют аналогичным правила по умолчанию, такие как POST.
  • DELETE правила по умолчанию для метода встроены в метод GET.

Здесь под примитивными типами я подразумеваю такие типы, как int а сложные типы - это классы, которые мы создаем.

Вы можете решить проблему, с которой имеете дело, применив любое из уже упомянутых другими решениями - например, переместив сложный тип в тело запроса. и передача примитивного типа через строку запроса ИЛИ обертывание как примитивных, так и сложных типов в единую модель и десериализации тела запроса в тип модели (который h выполняется как часть привязки параметров по сути).

0 голосов
/ 04 августа 2020

Попробуйте изменить маршрут на:

[Route("/jobApi/RunBD/{month}")]
public int RunBDReport([FromUri]int month, [FromBody] IEnumerable<ClientModel> clients)

Полезные данные необходимо передать в виде массива, как в ответе Джонатана.

0 голосов
/ 04 августа 2020

Попробуйте:

{"month":7,
"clients":[{"blockOfBus":"XXX",
"clientId":"123456",
"location":"",
"suppressSsn":"N"}]}

Похоже, что ваш ClientModel перечислимый неправильно назван в полезной нагрузке

...