0

I want to make a common change to all the resources an API exposes. For instance, suppose an API exposing all the students of a class, and you want to set a common course for all of the students.

One way would be to query the API, and one-by-one or in batch update a property of resources. However, that would require first getting all the resources, then update their property, and then send and post request.

Instead, I am interested in a RESTful design where you can send a property and its value, which will be applied on all the resources exposed via an API (e.g., students in the previous example).

Any suggestion on how this can be achieved via a RESTful design?

Update 1:

In other words, I would like to update one field of all the resources to a common value without having to fetch the resources first. So, I do not want to implement something as the following, because I have millions of resources that I do not want to fetch all their IDs first and then create a json object as the following:

PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]
Dr. Strangelove
  • 2,725
  • 3
  • 34
  • 61

3 Answers3

1

Use PATCH. Reference RFC5789 and RFC6902 for more details.

Sample:

PATCH /api/classes/123/students
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]

You will have to choose how to handle error your response, either making it atomic or not.

  • For atomic, a failed row will make your whole request 400.
  • For non-atomic, you'll have 200 from the server with error details in its body.

Both cases have pros and cons from API consumer perspective. Decision should be made in regard to your use case.

Update 1:

By not supplying a list to an endpoint without specific ID, you're doing that action with the whole collection.

Providing a JSON body like this should be setting all provided properties to value specified for every records in that collection:

PATCH /api/classes/123/students
{ courses: [ commonCourse1, commonCourse2 ] }
Community
  • 1
  • 1
  • you still rely on `classes` but in my scenario there could be cases where I don't have any synonym to `class` (e.g., `name` as in my question, that necessarily there is no model for it). – Dr. Strangelove Oct 02 '19 at 05:53
  • @Hamed I use `classes` as example in regard to your question where you want to set a common course for all of the students in a class. You can actually use this approach with any collection. As for the `name` you mentioned, I see you assign different name for each item, but I understand from your question that you want to update one field of all the resources to a common value? I'm a bit confused here. – Atthaporn Thanongkiatisak Oct 02 '19 at 07:38
  • Yes, I would like to update a field of all the resources to a common value. – Dr. Strangelove Oct 02 '19 at 16:46
  • @Hamed If that's the case, then the solution I provided is essentially that. Just specify the values you want and PATCH them into the collection. The example I provided will update every students inside class 123 to have their `courses` updated to a common value provided in request body. You can just remove `classes` from the url if you want to specify it for every students regardless of their class. I don't understand why did you mention `classes` at all in the first place. – Atthaporn Thanongkiatisak Oct 08 '19 at 03:45
0

If the students are already allocated to a class then I don't think there's a problem with changing them en-bloc with something like:

/api/class/123/updateCourse?newCourse=456

class ClassController
{
   public IResult UpdateCourse(int class, int newCourse)
Neil
  • 11,059
  • 3
  • 31
  • 56
0

You can still create an endpoint just like /items/update/all and pass your value:

POST /api/items/update/all 
{
  "value": 123
}

Next you just need properly handle it. For example, just write SQL query like:

UPDATE Items
SET value=POST["value"];