RESTful API : Should we create separate controller to manage many-to-many relationship

Viewed 31

What is the Best Rest practice to manage Many to many relationship in .net Core API

Here are 2 example models and mappings.

Users and Teams

  • One user can belong to many Teams

  • One Team can have many users

So to model this relationship we have a mapped table with UserTeams (Id, UserId, TeamId)

Scenario 1. When User is created ,Its associated teams will be assigned to it with POST

POST /users/user

Scenario 2 We need to provide the option in Teams to add more users in a given team.

PUT /teams/{1}/users [provide a list of user ids]

Scenario 3 Add more Teams for a particular user

PUT /users/{1}/teams [provide a list of team id]

What is REST best practice should we use the same pattern as mentioned above or to Create a new Controller UserTeams to manage user and teams relationship.

One more scenario

In Get Teams, We need to get the list of all Users. This will be the only GetbyId on TeamsController so should we just call it

Get /teams/{id}

or

Get /teams/{id}/detail [As it also include User Details]

1 Answers

I can come up with these 4:

1.) membership in teams

GET /teams/{tid}/users
PUT /teams/{tid}/users [{uid1},{uid2},...]
DELETE /teams/{tid}/users/{uid}

2.) membership in users

GET /users/{uid}/teams
PUT /users/{uid}/teams [{tid1},{tid2},...]
DELETE /users/{uid}/teams/{tid}

3.) membership with membership id

GET /memberships/?user={uid}&team={tid}
GET /memberships/?user={uid}
GET /memberships/?team={tid}
GET /memberships/{mid}
POST /memberships/ {uid,tid}
DELETE /memberships/{mid}

4.) membership with user id and team id

GET /memberships/user-{uid}/team-{tid}
GET /memberships/user-{uid}/
GET /memberships/team-{tid}/user-{uid}
GET /memberships/team-{tid}/
POST /memberships/ {uid,tid}
DELETE /memberships/user-{uid}/team-{tid}

You can support all 4 in parallel if you want to.

Now that I think about it, I can come up with another 2:

5.) membership in teams

GET /teams/{tid}/members
PUT /teams/{tid}/members [{mid1},{mid2},...]
DELETE /teams/{tid}/members/{mid}

6.) membership in users

GET /users/{uid}/memberships
PUT /users/{uid}/memberships [{mid1},{mid2},...]
DELETE /users/{uid}/memberships/{mid}

So what I don't like in the 1.) and 2.) solutions that we are talking about memberships here and the memberships belong to both the teams and the users. Since path is for describing a hierarchy the 1.) and 2.) tells me that teams contain users and users contain teams, which is not true, because they are independent of each other. The teams can exist without a certain user and the user can certainly exist without a team. So I would rather talk about memberships which cannot exist without teams and users, but both teams and users can exist without memberships. Well it is possible to have an empty team...

So I would go with the combination of 3.) + 5.) + 6.) if I want to be very verbose. It is important to have the right model here, because if you have memberships, you can add membership properties like since when, who allowed it or who invited the new member, when it ended, how much did they pay for it, what is the title of the member, etc. So it is really important to have the right model here. Ofc. if all you want to manage is the existence of the membership at the current time, then probably 1.) and 2.) is ok too.

Related