Come progettare RESTful Web Api per rappresentare le risorse

0

Sto sviluppando un web API ASP.NET Web Api 2 RESTful con .NET Framework 4.5.1 e C # e sto cercando di capire come esporre le risorse tramite un API Web:

Immagina di essere un proprietario di un gruppo e sono l'unico in grado di aggiungere nuovi utenti a quel gruppo (sto provando a simulare un gruppo WhatsApp).

Questa è la mia classe C # per l'utente:

public class User
{
    public int UserId { get; set; }
    public string UserName { get; set; }

    public List<Group> Groups { get; set; }
    public List<Group> GroupsOwned { get; set; }
}

E classe del gruppo:

public class Group
{
    public int GroupId { get; set; }
    public string GroupName { get; set; }

    public User Owner { get; set; }

    public List<User> Members { get; set; }
}

Come devo esporre i membri di proprietà dei gruppi dell'utente in un RESTful Web Api?

Penso di doverlo esporre in questo modo:

"api/users/{ownerId}/groupsOwned/{groupId}/members/"

Consentirò a PUT di modificare il gruppo per aggiungere un nuovo membro e probabilmente GET per ottenere tutti i membri.

Qualche consiglio?

    
posta VansFannel 09.09.2014 - 13:06
fonte

4 risposte

1

Perché vuoi aggiungere il proprietario (che sembra più un attributo di un gruppo) nell'URL? Può avere senso, ma non vedo un argomento per questo. / api / groups / {groupId} / members sembra avere più senso? Quindi puoi aggiungere un altro percorso: / api / users / 1 / groups e / api / users / 1 / groupsOwned dove mostri una collezione di link agli url di gruppi normali.

Because I need to pass the ID for the user that is modifying the group. If the user is the owner, he can add more members to the group.

In generale ciò suona come sicurezza e dovrebbe essere corretto dalle intestazioni (come Basic Auth, OAuth eccetera). Non cambia la risorsa che mostri. Ancora meglio: quando il proprietario di un gruppo cambia tutti gli URL non sono validi e non è riposante. Quindi suggerirei di lasciarli via e renderli un attributo.

Interessante da leggere quando si tenta di lavorare riposati è il concetto che l'autore ha: Roy Fielding è l'inventore del concetto REST e qui puoi trovare alcune nozioni di base sul concetto reale:

link

    
risposta data 16.09.2014 - 16:27
fonte
1

Dal tuo modello-oggetto concludo, che hai almeno due risorse distinte :

  • utenti
  • gruppi

Quindi ci sono due base-URL :

(1) /api/users/ e (2) /api/groups/

(1) offre:

/api/users/ GET mostra tutti gli utenti disponibili Risposta: la rappresentazione di tutti gli utenti

/api/users/?group=someGroup GET mostra tutti gli utenti membri di someGroup Risposta disponibile: la rappresentazione di tutti gli utenti del gruppo

/api/users/{id} OTTIENI per mostrare la risposta dell'utente individuale: la rappresentazione di un utente

/api/users/{id}/groups OTTIENI per mostrare i gruppi di singoli utenti Risposta: la rappresentazione dei gruppi di un utente

/api/users/ POST per creare un nuovo utente Risposta: l'URI del nuovo utente

/api/users/{id} PUT / PATCH per aggiornare un utente esistente Risposta: Nessun contenuto

/api/users/{id} DELETE per eliminare un singolo utente Risposta: Nessun contenuto

(2) offre:

/api/groups/ GET mostra tutti i gruppi disponibili Risposta: la rappresentazione di tutti i gruppi

/api/groups/{id} OTTIENI per mostrare la risposta del singolo gruppo: la rappresentazione di un gruppo

/api/groups/{id}/members OTTIENI per mostrare i membri del gruppo individuale Risposta: la rappresentazione del membro di un gruppo

/api/groups/ POST per creare un nuovo gruppo Risposta: l'URI del nuovo gruppo

/api/groups/{id} PUT / PATCH per aggiornare un gruppo esistente Risposta: Nessun contenuto

/api/groups/{id} DELETE per eliminare un singolo gruppo Risposta: Nessun contenuto

Di solito rispondi ad ogni richiesta, se non altrimenti consigliato, con 200 OK .

Imagine that I'm a group owner and I am the only one that can add new users to that group

Questo non ha importanza per la tua API. Che un utente sia autorizzato a fare qualcosa o no è un problema secondario. Se desideri aggiungere un utente a un gruppo, la tua API potrebbe fornire uno (o entrambi) dei due modi

  • /api/groups/{id}/members PUT / PATCH Aggiungi membri del gruppo
  • /api/users/{id} PUT / PATCH aggiorna utente singolo

Se un utente non è autorizzato a eseguire l'azione scelta, il server dovrebbe rispondere con 403 Proibito

Because I need to pass the ID for the user that is modifying the group. If the user is the owner, he can add more members to the group.

Poiché l'utente ha effettuato il login, hai il suo ID. Potresti facilmente salvarlo insieme alle informazioni aggiornate.

    
risposta data 09.09.2014 - 21:36
fonte
0

Quando dici "esporre i membri di un gruppo di utenti in un RESTful Web Api?" Questo potrebbe significare due cose:

  • Struttura URI (sembra che tu l'abbia già identificata)
  • Rappresentazione delle risorse (html, json, ecc.)

Se parli di rappresentazione, la mia preferenza personale è JSON HAL . Permette un modello davvero semplice di _links , _data , _embedded che aiuta a determinare la discoverabilità e la connettività.

Dai tuoi commenti sembra che tu voglia sapere come accedere ai membri. Questo è semplicemente

api/users/{ownerId}/groupsOwned/{groupId}/members/{memberId}

O se vuoi accedere a tutti i membri:

api/users/{ownerId}/groupsOwned/{groupId}/members/

Ma fai attenzione, dovresti davvero usare rappresentazioni nidificate della risorsa quando restituisci una collezione di risorse come avrebbe prodotto l'URI sopra. Guarda le specifiche HAL sopra, che ti aiuteranno a spiegare come incorporare le risorse in risorse.

Modifica

I think I have to expose it this way:

"api/users/{ownerId}/groupsOwned/{groupId}/members/" I will allow POST to add new members, and probably GET to get all members.

Sì, è corretto

    
risposta data 09.09.2014 - 13:45
fonte
0

Quando costruisci un servizio REST, provo a concentrarmi sull'oggetto in questione e ad usare il JSON per rappresentare la struttura dei dati.

In questo esempio, l'oggetto da modificare è il gruppo. Lo metterei alla base dell'URI e non farlo seppellire nel mezzo.

/api/groups/{groupId}

Questo dovrebbe essere valido perché gli ID di gruppo ( si spera ) sono unici all'interno dell'applicazione.

La prossima è la domanda su come aggiornare i membri.

Immagino un JSON che assomigli a qualcosa del tipo:

{
    "groupId": "1111",
    "groupName": "A Group",
    "ownerId": "2222",
    "membersIds": [ "2222", "3333", "4444" ]
}

La prima opzione sarebbe quella di PUT l'intero oggetto.

PUT /api/groups/1111

{
    "groupId": "1111",
    "groupName": "A Group",
    "ownerId": "2222",
    "membersIds": [ "2222", "3333", "4444" ]
}

Questa è una semplice API. Un client utilizza un GET per ottenere i dati correnti, apportare modifiche, quindi inserire il risultato. Spetterebbe al server convalidare l'aggiornamento nel suo insieme o rifiutare l'aggiornamento nel suo complesso se c'è qualche errore.

Capisco che questo potrebbe non essere sempre auspicabile, quindi potrei capire di volere un collegamento che aggiornerebbe solo i membri.

A tal fine ecco la scorciatoia per i membri:

/api/groups/{groupId}/members

con il JSON corrispondente:

[ "2222", "3333", "4444" ]

Questo sarebbe ancora un PUT perché stai aggiornando i dati esistenti.

PUT /api/groups/1111/members

[ "2222", "3333", "4444" ]

Il PUT sostituisce tutti i membri correnti con i membri dell'array. I membri attuali potrebbero essere richiesti con GET /api/groups/1111/members . Sarebbe responsabilità del cliente aggiungere nuovi membri ai membri correnti.

Questo non è ancora quello che hai chiesto. Vuoi un collegamento per aggiungere semplicemente membri. Qui il mio metodo si rompe. Non si sta utilizzando l'URI per rappresentare la struttura dei dati, si sta utilizzando l'URI per eseguire un'azione con i dati. Questo non è molto RESTful (IMHO), ma molte persone lo fanno.

In passato, ho utilizzato i parametri CGI per mostrare esplicitamente un'azione.

/api/groups/{groupId}?action=addMembers

Finalmente arriviamo a qualcosa che assomiglia a quello che hai chiesto.

POST /api/groups/1111?action=addMembers

[ "3333", "4444"]

Per me, non sembra molto RESTful, ma l'utilità supera l'ideologia e se questo è esattamente ciò di cui hai bisogno, allora eccolo qui.

    
risposta data 09.09.2014 - 15:23
fonte

Leggi altre domande sui tag