Reputation: 39354
I am creating a Web Api with ASP.NET Core and I have the following:
public class MessageApiController : Controller {
[HttpGet("messages/{id}")]
public async Task<IActionResult> GetById() { }
}
public class UserApiController : Controller {
[HttpGet("users/{id}")]
public async Task<IActionResult> GetById() { }
}
Now I need to get all messages for a user. I know two options:
[HttpGet("messages")]
public async Task<IActionResult> GetMessagesByUser(Int32 userId) { }
Or
[HttpGet("users/{userId}/messages")]
public async Task<IActionResult> GetMessagesByUser(Int32 userId) { }
I have a few questions:
Upvotes: 0
Views: 43
Reputation: 64121
It depends on how you want your consumers to use the service.
The question you need to ask yourself, does it make sense to call /messages
to obtain all messages (from all users) or should it only be ever possible to obtain messages from 1 user (and exclude the possibility to ever obtain messages from all users).
This question is important, because it will tell you which one to use or if you should use both.
When there is no plans to ever allow users to obtain message from all users, you better go with users/{userId}/messages
because this will enforce this rules. In this case users/{userId}/messages
is a resource of messages for user userId
.
On other side, the expectation is that messages
will allow you to query all users messages or at least the ones the user has permission too (i.e. an administrative user would get all users messages back on this endpoint) and you could filter this via query parameters (rather than encoding in the path). If you do not want this, then messages
will be an invalid route or just misleading.
- Which is more common? I think I could even use both ...
users/{userId}/messages
is more expressive and from the url it's clear, that you want all messages from a given user.
messages
can be used, if you also have a permission system to allow certain users see messages from other users (i.e. a companies worker should be able to see all messages of the company, not just the ones sent directly to him) with query filters to reduce this (by single or multiple users).
- When using "users/{userId}/messages" would you place this action in MessageApiController or UserApiController?
To MessageApiController
, because it's operating on the message, not on the user. The user is just a mandatory parameter.
On a side note:
You can simplify your controller routings by putting a route on the controller type rather than having the route template completely on the action.
[Route("[controller]")]
public class MessageController : Controller
{
[HttpGet("id}")]
public async Task<IActionResult> GetById()
{
}
}
Notice that I removed the "Api" from controller name, because the [controller]
placeholder takes the class name minus "Controller" as route parameter. The Route on MessageController
acts as prefix, so GetById()
still gets message/{id}
as a route, but you don't have to repeat the "message" part on each action.
Upvotes: 1