Reputation: 14535
I have an OData endpoint (action method) that returns an IQueryable
list of items:
[EnableQuery]
public IQueryable<Entity> Get()
The POCO class has the [Key]
attribute applied to its id property. It works fine, all entities are returned and I can do filters, etc. But I cannot select an instance by its id, that is:
/odata/entity?$filter=Id eq 1 //works
/odata/entity(1) //does not work
Is there any setup that I need to do? I also tried configuring the key in the model:
var odataBuilder = new ODataConventionModelBuilder();
odataBuilder.EntitySet<Student>("Entity").EntityType.HasKey(x => x.Id);
But it also dit not work. The only way I can achieve this is by adding an action method specifically for this:
public Entity Get(int key) //works
But I was under the impression that this would not be needed, the other action should be enough. Am I wrong?
Upvotes: 2
Views: 872
Reputation: 4450
TL;DR: use ODataRoutePrefix + ODataRoute because [Route("api/[controller]")]
can't handle OData api/todo(10)
for single navigable entity.
To get the OData convention for api/todo(10)
working:
// Startup - Configure()
app.UseEndpoints(endpoints =>
{
endpoints.Count().Filter().OrderBy().Expand().Select().MaxTop(100);
endpoints.MapODataRoute("odata", "odata", GetEdmModel())
.EnableDependencyInjection();
//[Route("odata/[controller]")] // remove this
[ODataPrefix("todo")] // add this
public class TodoController : ODataController {
// /odata/todo?$filter=id eq 142
[EnableQuery]
public IQueryable<Todo> Get(
[FromServices] MyDataContext dataContext)
{
return dataContext.Todo;
}
[EnableQuery]
[ODataRoute("({id})")] // /odata/todo(142)
public IActionResult GetByKey(
[FromODataUri] long id,
[FromServices] MyDataContext dataContext)
{
return Ok(dataContext.Todo.SingleOrDefault(x => x.Id == id));
}
None of the OData samples for ASP.NET Core use [ODataRoutePrefix]
and [ODataRoute]
but those are necessary for routing using OData convention api/todo(10)
.
If you use normal [Route("api/[controller]")]
on controller and [Route("({id})"]
on GetByKey()
then your route is
~/api/todo/(10)
- BADBAD~/api/todo(10)
- GOOD.. the later is the convention used in many samples including https://www.odata.org/getting-started/basic-tutorial/ .
This also seems to break the helper Created(todo)
used in POST
samples, because it can't find api/todo({newId})
route to return in the Location header.
Upvotes: 2
Reputation: 14535
Based on my research and the examples found, I don't think this is possible, e.g., there is always a need for a dedicated method for this.
Upvotes: 2