I've created a fresh ASP.NET Core 2.1 API project, with a Data
dto class and this controller action:
[HttpPost]
public ActionResult<Data> Post([FromForm][FromBody] Data data)
{
return new ActionResult<Data>(data);
}
public class Data
{
public string Id { get; set; }
public string Txt { get; set; }
}
It should echo the data back to the user, nothing fancy. However, only one of the two attributes works, depending on the order.
Here's the test requests:
curl -X POST http://localhost:5000/api/values \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'id=qwer567&txt=text%20from%20x-www-form-urlencoded'
and
curl -X POST http://localhost:5000/api/values \
-H 'Content-Type: application/json' \
-d '{
"id": "abc123",
"txt": "text from application/json"
}'
I've tried several approaches, all to no avail:
- Creating a custom child
BindingSource
, but that's only metadata it seems. - Using an attribute
[CompositeBindingSource(...)]
, but the constructor is private and this might not be intended usage - Creating an
IModelBinder
and provider for this, but (1) I might only want this on specific controller actions and (2) it's really a lot of work seemingly to get the two inner model binders (for Body and FormCollection)
So, what is the correct way to combine FromForm
and FromBody
(or I guess any other combination of sources) attributes into one?
To clarify the reason behind this, and to explain why my question is not a duplicate of this question: I want to know how to have the same URI / Route to support both different types of sending data. (Even though perhaps to some folks' taste, including possibly my own, different routes/uris might be more appropriate.)