I have a Product odata controller and a Product Category odata controller.
They are both using entity framework entities and have navigation methods used for odata expan
According to your description, it seems that you need to add the [EnableQuery]
attribute to the controller method for the stored procedure.
The following implementation works for me:
In WebApiConfig.cs
:
builder.EntityType<Product>().Function("SomeFunction").ReturnsFromEntitySet<Product>("Products");
In ProductsController.cs
:
[HttpGet]
[EnableQuery]
public IHttpActionResult SomeFunction()
{
return Ok(products.FirstOrDefault(c => c.ID == 1));
}
In browser:
GET http://localhost:54017/Products(1)/Default.SomeFunction()?$expand=Categories
gives
{
@odata.context: "http://localhost:54017/$metadata#Products",
value: [
{
ID: 1,
Name: "Some",
Categories: [
{
ID: 1,
Name: "Some"
}
]
}
]
}
Updated on 10/22/2014:
I've modified the code you attached and attach it down below. Would you try if it works?
[HttpPost]
[EnableQuery(PageSize=10)]
public IHttpActionResult SomeFunction()
{
var results = db.SomeStoredProc().ToList();
return Ok(results);
}
Similar function worked in my tests. The reason that this would work is that Web API OData handles the $skip
, $top
, and paging for you automatically. You don't need to worry about applying them to your result. The query options from the client will be applied to the whole set you return.
Here is the code I used to fix the problem.
By no means is it "correct" code.
For example: ODataQueryOptions.Top / Skip will be null if used on an Action that contains ODataActionParameters.
ODataActionParameters will contain the Top / Skip as a parameter? Very odd.
So I added both in the hopes that Microsoft or someone else can fix this issue in the future.
Controller:
[HttpPost]
[EnableQuery]
public PageResult<SomeObject> SomeFunction(ODataQueryOptions<SomeObject> options, ODataActionParameters parameters)
{
// Get the paging settings from ODataActionParameters since they are not shown on the ODataQueryOptions. Maybe there will be some fix for this in the future.
int pageSize = (int)parameters["pageSize"];
int take = (int)parameters["take"];
int skip = (int)parameters["skip"];
int page = (int)parameters["page"];
// Apply page size settings
ODataQuerySettings settings = new ODataQuerySettings();
// Create a temp result set to hold the results from the stored procedure
var tempResults = db.SomeStoredProc().ToList(); // ToList is required to get the "real" total count before paging
// Apply the query options. For now this is only needed to get the correct count since the options does not seem to contain the TOP / SKIP when using OData parameters.
IQueryable results = options.ApplyTo(tempResults.AsQueryable(), settings);
// This was needed for custom paging. EXAMPLE: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options
return new PageResult<SomeObject>(tempResults.Skip(skip).Take(take),
Request.ODataProperties().NextLink,
Request.ODataProperties().TotalCount);
}
Then WebApiConfig:
var SomeFunction = builder.Entity<SomeObject>().Collection.Action("SomeFunction");
SomeFunction.Parameter<int>("take");
SomeFunction.Parameter<int>("skip");
SomeFunction.Parameter<int>("page");
SomeFunction.Parameter<int>("pageSize");
SomeFunction.ReturnsCollectionFromEntitySet<SomeObject>("SomeObjects");