Search code examples
asp.net-coreroutesoverridinghierarchical

.net core api hierarchical routing


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.


Solution

  • 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().