I'm building an api, and I want to be able to use hierarchical routing such as:
api/category/1234/product
api/category/1234/product/5678
Currently I'm using a Route attribute on the ProductController: [Route("api/[controller]")]
This is because most of my routing follows that convention.
I have a method on the ProductController:
[HttpGet]
[Route("/api/category/{categoryId:int}/product")]
public IActionResult GetAllByCategoryId(int categoryId)
{
var products = _productRepo.Query(p => p.CategoryId == categoryId);
return Ok(products);
}
Hooray, it returns data for api/category/{categoryId:int}/product
but it will still return the data for api/product/{categoryId:int}
because of the Route attribute on the controller.
My question is:
Is there a way to override the controller route template?
The only alternative option I can think of at the moment is to place a Route attribute on every single method. There has to be a better way to deal with hierarchical routing.
but it will still return the data for api/product/{categoryId:int} because of the Route attribute on the controller.
This is not quite right. Your GetAllByCategoryId()
action will be accessible only by /api/category/{categoryId:int}/product
as you specified in action-level Route
attribute.
If you send HTTP GET for api/product/12345
and receive some data back, probably you have some other action in the controller that processes the request. It will probably have one of the following routing attributes:
[HttpGet("{id}")]
public IActionResult Get(int id)
{
// ...
}
or
[Route("{id:int}")]
public IActionResult Get(int id)
{
// ...
}
So just debug your controller and check what action is actuall executed. I bet it will not be GetAllByCategoryId()
.