Home > Software design >  HTTP GET - With Body and URI parms - [FromBody] variable is null
HTTP GET - With Body and URI parms - [FromBody] variable is null

Time:06-01

I have an endpoint that has been implemented as a POST. It's actually idemponent and really could be / should be a GET but because the data required includes a collection or a list, I changed it to a POST with a json body.

But the team finds this confusing. So now I'm being asked to implement as a GET with both URI parameters and a list in the body as JSON.

So essentially what I need to do is something like this:

 GET http://localhost:123/locations/{locationID}/products/{productID}/stats/{dateRange}
 
 Body:  {"count":["exports","imports","anothertiem", "thisListCanbeLong"]}

I've tried to change my c# function signature to look like this:

    [HttpGet]
    [Route("/locations/{locationID}/products/{productID}/stats/{dateRange}")]
    [AllowAnonymous] 
    public ProductStats GetStats(ProductStatRequest request, [FromBody] List<string> typesofStats)
    {

And then when I try to call the endpoint using either Talent or Postman using this type of a request:

 http://localhost:123/locations/4/products/all/stats/15

Headers:

 Content-Type header is set to "application/json"

Body

{"count":["exports","imports","anothertiem", "thisListCanbeLong"]}

the call fails the typeofStats list is null. Not sure how I can extract the body in this type of an endpoint.

Also, while I did read that GET can handle body, maybe this isn't the best approach. Maybe the POST is better and I just have to get back to the team and say no, or maybe the POST can handle both URI parms and body. The issue for the team is that they want to see in the uri the location id being passed and the product id etc - to keep it uniform with the rest of the calls.

Thanks for the help.

CodePudding user response:

The Asp.net MVC framework works with naming conventions, which means that the parameter names must match the request data names. With the following changes should work:

[AllowAnonymous, HttpGet("/locations/{locationID}/products/{productID}/stats/{dateRange}")]
public ProductStats GetStats(
    [FromRoute] ProductStatRequest request, 
    [FromBody] List<string> typesofStats)
{
    return new ProductStats
    { 
        Request = request,
        TypesOfStats = typesofStats
    };
}

public class ProductStatRequest
{
    public int LocationId { get; set; }

    public string ProductId { get; set; }

    public int DateRange { get; set; }
}

public class ProductStats
{
    public ProductStatRequest Request { get; set; }

    public List<string> TypesOfStats { get; set; }
}

... and the request/response from postman

enter image description here

If you want to provide an object with a list in it in the body of the request, you should expect the same object in the action method.

{"count":["exports","imports","anothertiem", "thisListCanbeLong"]}

should be expected as:

public class StatsTypes
{
    public List<string> Count { get; set; }
}
  • Related