Passing List object and int to web api

回眸只為那壹抹淺笑 提交于 2021-01-28 23:09:55

问题


I have a web api core project that if I send just the list parameter than the API receives the values, however if I send both parameters that the controller is looking for then both parameters are seen as null

My contoller:

[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; }
}

The request I am sending:

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

This causes both parameters to be seen as null by the controller, however if I send my request like this:

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

Then the controller is able to see the list object I am sending (however it obviously returns 500 as the model is not valid)


回答1:


[FromBody] can only be used once since the request body can only be read once.

Don't apply [FromBody] to more than one parameter per action method. Once the request stream is read by an input formatter, it's no longer available to be read again for binding other [FromBody] parameters.

Reference Model Binding in ASP.NET Core

Create a single model that matches the expected data.

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

And update the action accordingly

[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;
    }
}



回答2:


There can be only one parameter modified with [FromBody] attribute. So you need to either modify your method like this :

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

Then make the request like this :

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

Or modify both your method and model like this :

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

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

and then you can use the second request's body.




回答3:


Try:

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

It looks like your ClientModel enumerable is mistitled in the payload




回答4:


Try changing the route to:

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

The payload needs to be passed as an array, like in Jonathan's answer.




回答5:


There are few simple rules that help you get through these kind of issues when trying to pass data to your Web API endpoint. These are the default rules based on which the parameter binding happens. Based on these rules, you need to be applying the attributes like [FromBody] and [FromUri]

  • GET method call takes both primitive and complex types as a part of the query string
  • POST method call takes a primitive type parameter by default in the query string and the complex type needs to be passed as a part of the request body.
  • PUT and PATCH follow similar default rules as that of POST.
  • DELETE method's default rules are inline with the GET method.

Here by primitive types, I mean types like int and complex types are the classes that we create.

You can tackle the problem that you're dealing with by applying any of the solutions that others have already mentioned -- like moving your complex type into your request body and passing the primitive type through the query string OR wrapping both the primitive and complex types into a single model and deserialize the request body to the model type (which is done as a part of the parameter binding inherently).



来源:https://stackoverflow.com/questions/63254439/passing-list-object-and-int-to-web-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!