I want to achieve something close to the RateProduct action described in: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-actions
In that tutorial it is defined as:
[HttpPost]
public int RateProduct([FromODataUri] int key, ODataActionParameters parameters)
{
// ...
}
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Product>("Products");
// New Code
ActionConfiguration rateProduct = modelBuilder.Entity<Product>().Action("RateProduct");
rateProduct.Parameter<int>("Rating");
rateProduct.Returns<int>();
However, I have the use case of a Location entity that is smart enough to return other Locations within a certain radius around it. It should roughly be like this:
[HttpPost]
public IQueryable<Location> GetLocationsWithinRadius([FromODataUri] int key, ODataActionParameters parameters)
{
// Get the Location instance intended to be the center of the radius by using the key
// Do a radius search around it using (int)parameters["radius"] as the radius
// return the IQueryable<Location> of all location found within that radius
}
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Location>("Locations");
// New Code
ActionConfiguration getLocations = modelBuilder.Entity<Location>().Action("GetLocationsWithinRadius");
getLocations.Parameter<int>("radius");
getLocations.Returns<IQueryable<Location>>();
I would love to get this to work and currently it doesn't work when the the return type is an IQueryable<Location>
. If the return type is a primitive like an int, then it works, otherwise it gives the following error when I create a post in fiddler (the post is something like http://localhost:2663/odata/Locations(2112)/GetLocationsWithinRadius
and the Request Body is {radius: 50}
):
{
"odata.error":{
"code":"","message":{
"lang":"en-US","value":"An error has occurred."
},"innererror":{
"message":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata=minimalmetadata; streaming=true; charset=utf-8'.","type":"System.InvalidOperationException","stacktrace":"","internalexception":{
"message":"The related entity set could not be found from the OData path. The related entity set is required to serialize the payload.","type":"System.Runtime.Serialization.SerializationException","stacktrace":" at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)\r\n at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.<>c__DisplayClassa.<WriteToStreamAsync>b__9()\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)"
}
}
}
}
Is it possible to do what I am trying to accomplish? And if it is, dare I ask if the returned IQueryable<Location>
becomes composable with odata paramaters...(that would be nice)?
Thanks
OData expand functionality can be used to query related data. For example, to get the Course data for each Enrollment entity, include ?$ expand=course at the end of the request path: This tutorial uses Postman to test the web API.
The $value option is used to get individual properties of an Entity. There are two ways to get individual properties from an entity. We can get the response in either OData format or get the raw value of the property. We need to add method to the controller named GetProperty here property is a name of the property.
Looks like your action configuration is incorrect. Try the following and see if it works:
//getLocations.Returns<IQueryable<Location>>();
getLocations.ReturnsCollectionFromEntitySet<Location>("Locations");
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