I want to handle POST of the following API-Call:
/v1/location/deviceid/appid
Additional Parameter are coming from the Post-Body.
This all works fine for me. Now I wnat to extend my code by allowing "deviceid" and/or "appid" and/or BodyData to be null:
/v1/location/deviceid
/v1/location/appid
/v1/location/
These 3 URLs should responded by the same route.
My first approach (BodyData required):
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody] location_fromuser BodyData)
{
return repository.AddNewLocation(deviceid, appid, BodyData);
}
This does not work and returns a compile error:
"optional Parameters must be at the end"
Next try:
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post([FromBody] location_fromuser BodyData, string deviceid = null, string appid = null)
Now my function AddNewLocation() get always an BodyData=null
- even if the call send the Body.
Finally I set all 3 Parameter optional:
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody location_fromuser BodyData = null)
Don´t work:
Optional parameter
BodyData
is not supported byFormatterParameterBinding
.
Why do I want a solution with optional Parameters? My Controller handles just the "adding of a new Location" via a POST.
I want to send on wrong data my own exceptions or error messages. Even if the call has missing values. In this case I want to be able to decide to throw an exception or Setting Defaults by my code.
For an incoming request like /v1/location/1234
, as you can imagine it would be difficult for Web API to automatically figure out if the value of the segment corresponding to '1234' is related to appid
and not to deviceid
.
I think you should change your route template to be like
[Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]
and then parse the deiveOrAppid
to figure out the type of id.
Also you need to make the segments in the route template itself optional otherwise the segments are considered as required. Note the ?
character in this case.
For example:
[Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]