0

I have this list of Notes:

public static List<Note> _notes = new List<Note> { new Note { Id = new Guid("00000000-0000-0000-0000-000000000001"), CategoryId = "1", OwnerId = new Guid("00000000-0000-0000-0000-000000000001"), Title = "First Note", Description = "First Note Description" },
        new Note { Id = new Guid("00000000-0000-0000-0000-000000000002"), CategoryId = "1", OwnerId = new Guid("00000000-0000-0000-0000-000000000001"), Title = "Second Note", Description = "Second Note Description" },
        new Note { Id = new Guid("00000000-0000-0000-0000-000000000003"), CategoryId = "1", OwnerId = new Guid("00000000-0000-0000-0000-000000000001"), Title = "Third Note", Description = "Third Note Description" },
        new Note { Id = new Guid("00000000-0000-0000-0000-000000000004"), CategoryId = "1", OwnerId = new Guid("00000000-0000-0000-0000-000000000001"), Title = "Fourth Note", Description = "Fourth Note Description" },
        new Note { Id = new Guid("00000000-0000-0000-0000-000000000005"), CategoryId = "1", OwnerId = new Guid("00000000-0000-0000-0000-000000000001"), Title = "Fifth Note", Description = "Fifth Note Description" }
        };

I have these endpoints:

/api/notes GET
/api/notes POST
/api/notes/{id} GET
/api/notes/{id} PUT
/api/notes/{id} DELETE

I want to be able to DELETE/PUT/GET a resource based on OwnerID too. Right now, I can DELETE/PUT/GET a resource based on ID only. I have multiple solutions:

1) Do it from the OwnerController - /api/owner/{ownerId}/{noteId} 
2) Do it from the NotesController - /api/notes/{noteId}/{ownerId} 
3) Do it from the NotesController, on the GET/PUT/DELETE check if {id} matches either Id or OwnerId - I think that's not a solution, there might be collisions between those IDs.

From all of those I think that the second one might be what I need, but I'm not sure either.

In the REST api arhitecture, how would this case be treated?

Thanks.

4
  • Deleting a note (implying specifically one of possibly many) based on only a non-PK field sounds like there's something amiss in your modeling.
    – Flater
    Mar 21, 2022 at 20:33
  • @Flater this whole thing sounds strange to me. I don't understand why would you want to update/get a note based on both its ID and its OwnerID. But it is homework.... Mar 21, 2022 at 20:38
  • 1
    Use the examples of pets and their masters. There exists more than one pet called Rover - but a single pet owner will only have maximum one pet named Rover. If you never address pets except in scope of a single pet owner, you can make more assumptions about their uniqueness that way.
    – Flater
    Mar 22, 2022 at 7:22
  • A concrete answer can only be given once your data model is clear; which currently isn't the case. In order to find the needed info: (1) Do notes have their own PK? (2) Are you interested in handling notes (reading and/or writing) without needing to explicitly know who its owner is? (3) Will there ever be value to accessing a collection of notes that do not specifically belong to a specific owner? (4) My earlier comment repeated: describe what you want to have happen if an owner has multiple notes and you trigger a delete based only on the ownerID. Do all of the owner's notes get deleted?
    – Flater
    Mar 23, 2022 at 13:14

2 Answers 2

1

A given note can belong to exactly one owner, right? Maybe the ownerId should not be directly a part of a note payload? I would imagine the following API:

GET    /api/owner/{ownerId}/notes          # get all notes of an owner
POST   /api/owner/{ownerId}/notes          # add a note to the owner
DELETE /api/owner/{ownerId}/notes          # delete all notes of given owner
DELETE /api/owner/{ownerId}/notes/{noteId} # delete a note belonging to a given owner

If you want to stick to your original API, you can use query parameters to specify which notes you want to delete:

DELETE /api/notes?id=00000000-0000-0000-0000-000000000002
DELETE /api/notes?ownerId=00000000-0000-0000-0000-000000000002
2
  • If I use the first approach, will I still have those /api/notes endpoints or would they be useless? Mar 21, 2022 at 20:03
  • @OctavianNiculescu: It's only useless if it has no use. Is there value to fetching a list of notes without it being limited to a specific user? If not, then notes are a subresource of users. If so, then notes are their own resource and should have their own endpoint.
    – Flater
    Mar 23, 2022 at 13:15
1

In the REST api architecture, how would this case be treated?

REST doesn't care.

REST will tell you that we use "resources" as abstractions of information, and that resources are identified by uniform resource identifiers. It will tell you that you should be using hypertext to communicate to the client how resources can be manipulated.

But it doesn't tell you how to organize your resource model. If you want all of you information in one resource, that's fine. If you want to spread it out across several resources, that's also fine. Can the same information be in different resources? Yup, that's OK too.

REST also doesn't tell you what spelling conventions you should use for your resource identifiers (hint: URL shorteners work).

REST has nothing at all to say about the design of "controllers", because that's an implementation detail that is hidden behind the uniform interface.

Which is to say, designing the resource identifiers in your namespace, and designing the resources themselves, is on you.


If you have aspirations to be "web scale", then you are going to want to design your resources so that the fit well with caching semantics: the responses associated with each resource are cached separately, each with their own caching policy as described in the metadata of the HTTP response, unsafe requests that target a resource can trigger an automated invalidation of previously cached responses, and so on.

What we don't really have are general purpose mechanisms for communicating to the HTTP application that a message is expected to modify multiple resources. So you can have a form to submit when you want to modify all resources with a particular "owner" in your data model, and of course the controller that handles that request can do that.

But the "hierarchical part" of resource identifiers is something of a lie: general purpose HTTP components don't deduce semantics from identifier spellings -- there's no notion of a "cascading delete" or "cascading invalidation" based on some formula related to the resource identifiers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.