According to the docs here ...
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/odata-actions
...
Binding an Action to an Entity Set
In the previous example, the action is bound to a single entity: The client rates a single product. You can also bind an action to a collection of entities. Just make the following changes:
In the EDM, add the action to the entity's Collection property.
var rateAllProducts = builder.Entity().Collection.Action("RateAllProducts"); In the controller method, omit the key parameter.
[HttpPost] public int RateAllProducts(ODataActionParameters parameters) { // .... }
Why when I do this does it not work ...
Invoice Ref:
public class InvoiceReference
{
public string InvoiceNumber { get; set; }
public int SupplierId { get; set; }
}
Action setup:
var getByRefs = Builder.EntityType<SIHead>().Collection.Action("ByRefs");
getByRefs.CollectionParameter<InvoiceReference>("refs");
getByRefs.ReturnsCollectionFromEntitySet<SIHead>("SIHead");
Action method in the controller:
[HttpPost]
[EnableQuery]
[ODataRoute("ByRefs")]
public async Task<IHttpActionResult> ByRefs(ODataActionParameters p)
{
var refs = p["refs"] as InvoiceReference[];
// exception p is null
}
Example json content posted:
[
{
"InvoiceNumber": "5100011759|9800006622",
"SupplierId": 2
},
{
"InvoiceNumber": "5100012624|9800006635",
"SupplierId": 2
},
{
"InvoiceNumber": "5100012625|9800006636",
"SupplierId": 2
}
]
Seems to me that either I missed something or OData is broken.
After gettting some feedback from github (thanks Sam) I came to the conclusion that the way OData works means we must always post an object and never a collection directly ...
I missed some subtle / implied rules here ...
I have to provide an object (as a container) and not just the array I want to post. I can not bind directly to an ICollection, IList, List or Array only IEnumerable Out of curiosity: Why is this different to normal webAPI? The underlying binding framework in WebAPI's binding is awesome.
I'm not sure this "oddity" was / is well documented, it looks like no matter what I am posting I should always provide an object and never a collection directly in the body.
to post an array I therefore have to do ...
{ "foos": [1,2,3,4] }
.. instead of doing ...
[1,2,3,4]
... and then in the action always treat the posted collection as an Enumerable ...
Task PostStuff(ODataActionParameters p)
{
var foos = p["foos"] as IEnumerable<Foo>;
...
}
... I'm pretty sure this example is given somewhere but i'm pretty sure this requirement that the body always contain an object is not (i could be wrong). I guess this is to encourage people to build strongly typed request bodies (feels like a good call IMO).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With