1

I am using OData v3. How do I pass a parameter to an OData controller and return a collection? Example of what I am trying to do:

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<ServiceInfoResult> Get([FromODataUri] int instanceId)
{
    //etc
}

When I test this, I get this error:

No HTTP resource was found that matches the request URI 'http://localhost:30863/odata/ServiceInfoResultApi(1)'.
No action was found on the controller 'ServiceInfoResultApi' that matches the request.

I am aware of OData actions, but they are not a viable option on this case, because I need to get odata.count returned in the response, but no matter what I do, I cannot get that property returned when using OData actions (even when trying what was suggested here: Web API OData Inlinecount not working and here: Webapi odata expand with entity framework functions). So it would seem my only alternative was to create a new OData API controller for the ServiceInfoResult entity, so that I can avoid OData actions. However, as you can see above, passing in a parameter to a method that returns a collection seems to cause other errors.

Any solutions? And no, I can't update to OData v4, since that presents a whole host of other issues (it would take more time than I have and moreover, it doesn't support DateTime)

UPDATE

Thanks to @Fan Ouyang, I've discovered the reason for odata.count missing in the JSON payload is that I am not returning an entity type. If ServiceInfoResult were an entity in my database, odata.count would be returned. A bit silly that it's not being returned just because of that, but that's just how it is. I'm wondering if there's any workaround. For example, can I download the source code, change 1 line of code and use that? Otherwise, maybe it's time I started looking at OData v4. The project I have is quite big, so that's not a nice thought with the short amount of time I have. So, if there's any alternatives, I'd like to hear them. Thanks!

Community
  • 1
  • 1
Matt
  • 6,787
  • 11
  • 65
  • 112

2 Answers2

1

Try this sample, CheckoutMany method take parameter and return a collection https://github.com/OData/ODataSamples/tree/master/WebApi/v3/ODataActionsSample

Add [EnableQuery] attribute in the CheckOutMany action method, and add $inlinecount queryoption in requset url, you can see odata.count in payload

By the way, V4 support datetime now: http://odata.github.io/WebApi/#04-01-datetime-support

Fan Ouyang
  • 2,132
  • 1
  • 11
  • 13
  • Thank you for your comment. As I already said; I know about OData Actions, but I cannot use them in my situation because they do not return `odata.count` in the response. However, your link for V4 support or DateTime is interesting. Thank you. I might look at upgrading in future, but for now, I still need a solution for V3 – Matt Aug 05 '15 at 07:10
  • sorry for my unclear answer, and [EnableQuery] attribute in action, and add $inlinecount=allpages queryoption, odata.count is return in payload. – Fan Ouyang Aug 05 '15 at 07:34
  • Thank you again, but I know about `[EnableQuery]` and `$inlinecount=allpages`. It does not work with OData Actions. It seems to only work with normal HTTP GET methods and not OData Actions. When I try it with OData Actions, the payload only returns `odata.metadata` and `value`, but not `odata.count`. But thank you anyway for trying to help. – Matt Aug 05 '15 at 08:12
  • No, I'm pretty sure it work... I have download and modify the sample, the payload is like "odata.metadata":"...","odata.count":"2","value":[... – Fan Ouyang Aug 05 '15 at 08:18
  • OK, thank you. I will have a look at the sample project as you suggested. – Matt Aug 05 '15 at 08:35
  • I tested the sample project and it has not got `odata.count` in there. You can see for yourself when you test this OData Action: `public ICollection CheckOut(ODataQueryOptions opts)`.. you will only see `odata.metadata` and `value`. Which action were you looking at? – Matt Aug 06 '15 at 04:41
  • add [EnableQuery] in CheckOutMany method, modify the code in movies.js ajaxRequest("post", feedUrl + "/CheckOutMany", data) -> ajaxRequest("post", feedUrl + "/CheckOutMany?$inlinecount=allpages", data) – Fan Ouyang Aug 06 '15 at 04:51
  • I was being stupid and forgot to do as you just mentioned. However, I have just done it now and still no `odata.count`.. which is the problem I have in my own application as well.. same problem here. – Matt Aug 06 '15 at 07:03
  • are you sure you are calling the right method? you have to select more than one movie and click checkout and see the payload returned. – Fan Ouyang Aug 06 '15 at 07:06
  • Yes, I am 100% sure.. i have the correct method, I have the `[EnableQuery]` and I have modified the js file as you said.. I can see the request in both FireBug and also Fidler.. it is sending `$inlinecount`, but not recieving `odata.count` – Matt Aug 06 '15 at 07:08
  • Ok.. I uplaod the code for you https://github.com/VikingsFan/SampleForOData/tree/master/ODataActionsSample – Fan Ouyang Aug 06 '15 at 07:21
  • Thank you very much.. you have been very helpful. Yes, I can see it working now. I'm not sure what is wrong with my project.. maybe older versions of the OData DLLs or something.. I don't know. Anyway, now I can see it works fine; I will investigate some more and find out why it's not working in my project. Again, thank you for being very helpful! I will give you +1 for now and if I can make it work, then I will mark as answer. – Matt Aug 06 '15 at 07:48
  • I'm thinking maybe the problem with my project is the object I want to return is NOT actually an entity in entity framework. Because, I only see one difference: I use `ReturnsCollection` instead of `ReturnsCollectionFromEntitySet` in the web api config. Do you know if that is maybe the problem? Anyway, I will test.. – Matt Aug 06 '15 at 08:06
  • Yes.. I just tested it very quickly.. I created a new class called `MovieTest` with same properties as `Movie`. Then I changed `checkoutMany.ReturnsCollectionFromEntitySet("Movies");` to `checkoutMany.ReturnsCollection();` and of course the odata action method changed to return `ICollection`... now I see `odata.count` is missing again.. This is the problem I have. Do you have any solution? – Matt Aug 06 '15 at 08:11
  • In the spec inline count is just for entity type, so it doesn't work in v3 but work in v4 – Fan Ouyang Aug 06 '15 at 08:24
  • Thanks again. I updated my post with the info. I might just have to look at OData v4 soon... – Matt Aug 06 '15 at 08:30
  • I tried V4: the problem still exists.. with both the OData Actions and also the OData Functions – Matt Aug 18 '15 at 06:29
0

This was recently fixed with the release of version 5.7 (@odata.count is now returned for collections of complex types). More info here: https://github.com/OData/WebApi/issues/484#issuecomment-153929767

Matt
  • 6,787
  • 11
  • 65
  • 112