简体   繁体   中英

Inheriting route attribute in .NET Core Web API

Let say I am going to make the following REST APIs:

https://somedomain.com/api/Companies/{cid}

https://somedomain.com/api/Companies/{cid}/Employees/{eid}

https://somedomain.com/api/Companies/{cid}/Products/{pid}

In the above situtaion, I need routing ( Route() Attribute) to be extendable so that a routing hierarchy can be formed. I have tried different approach but all of them don't seem decent. Anyone can give me advice on how can I achieve routing inheritance like...

    [Route("api/CompaniesController/{cid}")]
    [ApiController]
    public class CompaniesController : ControllerBase
    {
    }

    [Route("Employees/{eid}")]
    public class EmployeesController: CompaniesController 
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }

    [Route("Products/{pid}")]
    public class ProductsController: CompaniesController 
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }

You shouldn't be using different controllers for this, you should be using actions in the same controller, so the actions can "inherit" the controller route.

I changed your example into this:

[Route("api/Companies/{cid}")]
[ApiController]
public class CompaniesController : ControllerBase
{
}

[HttpGet]
[Route("Employees/{eid}")]
public IEnumerable<string> GetEmployees(string cid, string eid)
{
    return new string[] { "value1", "value2" };
}

[HttpGet]
[Route("Products/{pid}")]
public IEnumerable<string> GetCompanies(string cid, string pid)
{
    return new string[] { "value1", "value2" };
}

Alternatively, if you want to keep the full route as your examples but want separate controllers (to avoid one single controller with dozens of actions), you can use separate controllers like this, just add the full route as you want on each controller:

[Route("api/Companies/{cid}")]
[ApiController]
public class CompaniesController : ControllerBase
{
}

[Route("api/Companies/{cid}/Employees/{eid}")]
public class EmployeesController: ControllerBase
{
    [HttpGet]
    public IEnumerable<string> Get(string cid, string eid)
    {
        return new string[] { "value1", "value2" };
    }
}

[Route("api/Companies/{cid}/Products/{pid}")]
public class ProductsController: ControllerBase 
{
    [HttpGet]
    public IEnumerable<string> Get(string cid, string pid)
    {
        return new string[] { "value1", "value2" };
    }
}

[Route("api/Companies/{cid}/Employee/{eid}/Privilege/{pid}/Account/{aid}")]
public class AccountsController: ControllerBase 
{
    [HttpGet]
    public IEnumerable<string> Get(string cid, string eid, string pid, string aid)
    {
        return new string[] { "value1", "value2" };
    }
}

So instead of inheriting a controller, you just add the full path in the controller route.

If inheriting a controller made the route be inherited as well, that could be a problem in the future. Image someone change one controller to inherit a new controller (thus introducing new piece of route to the url). That would not only affect the controller you are changing, but all children.

In my opinion, it's better if you don't have outside things possibly affecting how your route look like. Only the [Route] inside your controller can change it. It's simpler, easy to find what is being affected, easier to maintain, more explicit, nothing gets hidden by inheritance or outside code.

The question is: do you really need the full path in the route? Why not use just this instead:

  • api/Companies/{cid}
  • api/Employees/{eid}
  • api/Products/{pid}
  • api/Accounts/{aid}

That's a decision you should make.

As a side note, you may consider returning IActionResult instead of the actual objects. Also, you may want to use [FromRoute] in the parameters. Lastly, I used plural in the action method name as it's returning an array, but if you are providing id in the route, it suggests you are returning a single entity, not an array.

I encourage you to read ASP.NET Core Attribute Routing .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM