I am building RESTful API that manages persons and lists. There can be many List and many Person each with its own set of properties. Person can be in zero or more lists, List can contain zero or more Persons.

I have implemented these operations for Persons and Lists:

  • GET api/Persons/ to get all persons
  • POST api/Persons/ {..} to create new person
  • PUT api/Persons/123 {..} to update person by id
  • DELETE api/Persons/123 to delete person by id

To retrieve Lists person is in I would use GET /api/Persons/123/Lists, to retrieve all persons in List I would use GET /api/Lists/234/Persons.

How do I design API to add Person to Lists, remove them from Lists?

I thought about flattening Person to include Lists but then there will be other associations from Person and it seems unnecessary to transfer that mush information.

I am using asp.net Web API 2 but I am asking in general what are the design principles in this case.

有帮助吗?

解决方案

REST isn't carved in stone and this many-to-many relationship of nested resources is a very common problem with mostly two possible approaches. Which of the two is best for your specific case would depend on a few details and maybe how exactly asp.net handles things. But I will just describe both and explain why I mostly prefer the second approach.

Approach one would simply use the nested resources approach you already have. Doing

POST /api/Lists/234/Persons/123

would add Person 123 to list 234. This is simple and easy and you could see this used often enough but has a few disadvantages. (obviously you could mirror this and us POST /api/Persons/123/Lists/234 instead)

The second alternative is to handle it as a resource of its own named ListPersons (as you maybe already named the table holding the relationship information for this).

To create such a resource:

POST /api/ListPersons?list=234&person=123

similar to delete a person from a list or update the relationship. While at first this may seem a bit superficial it is most likely easier to implement and test. Also it keeps the controller actions simpler, since it lets them stay "single responsibility". The main advantage may be that if you later want to add additional data to the relationship adding this information was params will be easy and names can't clash with similar names in the other two tables.

As an example assume a List would be a team and later you decide to add the 'role' the Person (in this case a player) has in this team. You can easily add this like

POST /api/ListPersons?list=234&person=123&role=captain

even if the Person resource has a role (say the preferred role for this Person) by itself.

At least in Rails this has the additional advantage that within the controllers the action names can still reflect the REST verbs, while in approach one since create etc are already taken for the List itself you would have to come up with new names.

For completeness approach three would be to simply update a List with a param that contains a list of Persons. I would totally dislike this for many reasons so I just mention that this too is seen in the wild.

许可以下: CC-BY-SA归因
scroll top