I have created a new Web API project from the Visual Studio Templates and then I have followed the following tutorial for adding OData to this project. https://devblogs.microsoft.com/odata/supercharging-asp-net-core-api-with-odata/
Calling https://localhost:xxx/api/Assets and https://localhost:xxx/api/Assets/1
return all Assets, while the latter should return only 1 asset (where id = 1)
My code:
public class AssetsController : ControllerBase
{
private IAssetService _service;
private IMapper _mapper;
public AssetsController (IAssetService _service, IMapper mapper)
{
this._service = _service;
this._mapper = mapper;
}
[HttpGet]
[EnableQuery()]
public ActionResult<IEnumerable<Asset>> Get()
{
return this._service.GetAllAssets().ToList();
}
[HttpGet("{id}")]
[EnableQuery()]
public Asset Get(int id)
{
return _service.GetById(id);
}
}
I have debugged to verify that the Get(int id)
function is never called.
I have tried defining my route explicitly like this:
[HttpGet]
[Route("GetById/{id}")]
[EnableQuery()]
public Asset Get(int id)
{
return _service.GetById(id);
}
EDIT
Routing defined in startup:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
/* snip */
app.UseMvc(routeBuilder =>
{
routeBuilder.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
routeBuilder.Select().Filter().OrderBy().Expand().Count().MaxTop(10);
routeBuilder.MapODataServiceRoute("api", "api", GetEdmModel());
});
}
This makes no difference.
Any ideas?
There're two approaches to solve this question.
Approach 1 : rename the id
parameter to key
According to the OData v4 Web API docs :
Here are some rules for the method signatures:
- If the path contains a key, the action should have a parameter named key.
- If the path contains a key into a navigation property, the action should have a > parameter named relatedKey.
- POST and PUT requests take a parameter of the entity type.
- PATCH requests take a parameter of type Delta, where T is the entity type.
We should have a parameter named key
:
[HttpGet("{id}")] // actually, this line doesn't matter if you're using OData, but it's better to rename it to `key` too
[EnableQuery()]
public IActionResult Get(int key)
{
....
}
Approach 2: rename the Get
method to GetAsset
According to OData v4 Web API docs:
When Web API gets an OData request, it maps the request to a controller name and an action name. The mapping is based on the HTTP method and the URI. For example, GET /odata/Products(1) maps to ProductsController.GetProduct.
We could also rename the action method to GetAsset
as below:
[HttpGet("{id}")]
[EnableQuery()]
public IActionResult GetAsset(int id)
{
...
}