Modelleren van bewerkingen in de REST-service

Ik weet dat dit soort vragen eerder zijn gesteld. Ik heb een oplossing voor mijn probleem en ik wil weten of ik REST- of HTTP-principals overal verbreek.

In mijn systeem heb ik een resource genaamd member die de gebruikelijke GET/POST/PUT operaties ondersteunt. Lid heeft de status Actief en Uitgeschakeld . Ik moet de werking van het uitschakelen van de gebruiker modelleren. Ik begrijp waarom het volgen vanuit het REST-perspectief een slecht idee zou zijn

POST api/member/john.smith/disable

Ik heb een oplossing gelezen om een ​​bron te accepteren die het verzoek vertegenwoordigt om een ​​lid uit te schakelen, zoals hieronder

public class DisableMemberRequest
{
    public string Username {get; set;}
}

En dan een POST op bovenstaande bron

POST api/DisableMemberRequest

Hoewel deze aanpak redelijk lijkt, vind ik dat dit niet klopt in termen van schone API-interfaces. Het kan betwistbaar zijn of het antwoord van de bovenstaande aanvraag een 200 OK of 201 Created of 202 Geaccepteerd moet zijn.

Ik denk dat ik een nieuwe resource, genaamd DisabledMember , en een PUT op deze resource zou plaatsen, betekent dat een bepaald lid moet worden uitgeschakeld zoals hieronder

PUT api/disabledmember/john.smith

Dit lijkt een perfect geldig ontwerp vanuit REST/HTTP-perspectief voor mij. Maar ik ben geen expert en wil dit graag valideren met mensen die dit al lang doen.

BEWERK

Ik voeg deze gegevens toe na interactie met andere programmeurs op deze pagina. Het proces van het uitschakelen van het lid gaat niet alleen over het instellen van een statusvlag op het lid. Er zijn andere werkstromen die moeten worden geactiveerd wanneer een lid is uitgeschakeld.

7

9 antwoord

Een manier om dit soort dingen te doen, is om een ​​resource te definiëren die de set gehandicapte leden vertegenwoordigt. Om een ​​lid uit te schakelen, voegt u dat lid toe aan de set van uitgeschakelde leden. Het zou er ongeveer zo uit kunnen zien.

POST /api/DisabledMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Als u de bewerking wilt terugdraaien, kunt u het doen

POST /api/ActiveMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Deze aanpak heeft het voordeel dat het doen van GET/api/DisabledMembers een volkomen natuurlijk iets is om te doen. Door het gebruik van text/uri-list wordt het ook eenvoudig om een ​​set leden tegelijkertijd uit te schakelen/opnieuw te activeren.

4
toegevoegd
Laat me dit goed maken. Suggereert u dat PUT wordt aanbevolen voor een bepaalde payload terwijl POST in orde is zonder een payload? Ik ben niet erg duidelijk over dat aspect. Is er een artikel/blog dat meer over dit aspect vertelt?
toegevoegd de auteur Suhas, de bron
De reden dat ik PUT gebruik, is omdat de ID van de resource die bij het verwerken van dit verzoek is gemaakt, bekend is bij de klant, of met andere woorden: u bent PUT op een bekende URL. POST wordt meestal gebruikt als de client de URL van de resource die wordt gemaakt niet kent.
toegevoegd de auteur Suhas, de bron
Dat is vergelijkbaar met wat ik van plan ben te doen. Het enige verschil is dat u POST gebruikt in plaats van PUT
toegevoegd de auteur Suhas, de bron
@Suhas Welk mediatype zou u PUT? Ik veronderstel dat je met een lege body zou kunnen PUTEN en WISSEN om te reactiveren.
toegevoegd de auteur Darrel Miller, de bron
@Suas allebei tamelijk zeldzaam. Voor zover ik weet, heeft de HTTP-specificatie echter ook geen bezwaar.
toegevoegd de auteur Darrel Miller, de bron
@suhas PUT is perfect geldig. Zoals je al zei, het is gemakkelijk vrij eenvoudig om de uri van tevoren te bouwen, en het is idempotent. Dus, PUT is meer representatief voor de semantiek. Het enige rare is meestal dat je met PUT iets plaatst dat je wilt bewaren. In jouw geval is de actie van het doen van de PUT wat belangrijk is. Er is echt geen behoefte aan een payload.
toegevoegd de auteur Darrel Miller, de bron

Een manier om dit soort dingen te doen, is om een ​​resource te definiëren die de set gehandicapte leden vertegenwoordigt. Om een ​​lid uit te schakelen, voegt u dat lid toe aan de set van uitgeschakelde leden. Het zou er ongeveer zo uit kunnen zien.

POST /api/DisabledMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Als u de bewerking wilt terugdraaien, kunt u het doen

POST /api/ActiveMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Deze aanpak heeft het voordeel dat het doen van GET/api/DisabledMembers een volkomen natuurlijk iets is om te doen. Door het gebruik van text/uri-list wordt het ook eenvoudig om een ​​set leden tegelijkertijd uit te schakelen/opnieuw te activeren.

4
toegevoegd
Laat me dit goed maken. Suggereert u dat PUT wordt aanbevolen voor een bepaalde payload terwijl POST in orde is zonder een payload? Ik ben niet erg duidelijk over dat aspect. Is er een artikel/blog dat meer over dit aspect vertelt?
toegevoegd de auteur Suhas, de bron
De reden dat ik PUT gebruik, is omdat de ID van de resource die bij het verwerken van dit verzoek is gemaakt, bekend is bij de klant, of met andere woorden: u bent PUT op een bekende URL. POST wordt meestal gebruikt als de client de URL van de resource die wordt gemaakt niet kent.
toegevoegd de auteur Suhas, de bron
Dat is vergelijkbaar met wat ik van plan ben te doen. Het enige verschil is dat u POST gebruikt in plaats van PUT
toegevoegd de auteur Suhas, de bron
@Suas allebei tamelijk zeldzaam. Voor zover ik weet, heeft de HTTP-specificatie echter ook geen bezwaar.
toegevoegd de auteur Darrel Miller, de bron
@suhas PUT is perfect geldig. Zoals je al zei, het is gemakkelijk vrij eenvoudig om de uri van tevoren te bouwen, en het is idempotent. Dus, PUT is meer representatief voor de semantiek. Het enige rare is meestal dat je met PUT iets plaatst dat je wilt bewaren. In jouw geval is de actie van het doen van de PUT wat belangrijk is. Er is echt geen behoefte aan een payload.
toegevoegd de auteur Darrel Miller, de bron
@Suhas Welk mediatype zou u PUT? Ik veronderstel dat je met een lege body zou kunnen PUTEN en WISSEN om te reactiveren.
toegevoegd de auteur Darrel Miller, de bron

Je eerste twee suggesties ruiken een beetje, omdat ze een werkwoord in de URL hebben. Goede RESTful-architectuur definieert alleen zelfstandige bronnen, omdat het HTTP-protocol de set werkwoorden definieert die van toepassing is op die bronnen.

De andere suggestie is interessant, maar PUT suggereert dat je dan een GET kunt uitvoeren om een ​​representatie te krijgen van het ding dat je zojuist hebt geplaatst, wat niet heel veel oplevert zin in deze context.

Van wat je zegt, is er een aanzienlijk proces om het account van een gebruiker in of uit te schakelen en dat je het niet prettig vindt dat dit een PUT of PATCH operatie is om eenvoudigweg " zet een waarde om van waar naar false . Als dit enige tijd vergt, een overgangstoestand heeft en waarschijnlijk iets is dat u wilt blootstellen aan API-consumenten zodat zij zich bewust zijn van het proces, is het zinvol om het proces zelf als een soort hulpmiddel te definiëren:

Start deactivering:

POST api/members/deactivations

Krijg de huidige status van een deactivering of rapporteer over activiteiten die hebben plaatsgevonden:

GET api/members/deactivations/john.smith

Annuleer een deactivering die bezig is (optioneel):

DELETE api/members/deactivations/john.smith

Als u een account opnieuw kunt activeren, kan dit een vergelijkbaar patroon volgen.

Als u vindt dat er onvoldoende inhoud is om deze workflows te rechtvaardigen als hun eigen bronnen, of als u gewoon niet weet wat u moet antwoorden op GET , dan suggereert dit dat de werkstroom niet is zo belangrijk dat het niet zomaar voor de API-gebruikers kan worden verborgen en kan worden geactiveerd als neveneffect van het wijzigen van de actieve -waarde van de gebruiker.

3
toegevoegd
Het verschil is dat een deactivering duidelijk een "ding" is dat je onafhankelijk van andere bronnen kunt begrijpen, maar nog steeds sterk gerelateerd is aan leden .
toegevoegd de auteur Paul Turner, de bron
Ik denk dat, wat ik aanriep DisableMemberRequest , je deactivering aanroept. Ik vind het een goed idee om DELETE te gebruiken om het deactiveringsproces te annuleren. Maar nogmaals, dat is handig als uw deactivering een langlopend proces is.
toegevoegd de auteur Suhas, de bron

Je eerste twee suggesties ruiken een beetje, omdat ze een werkwoord in de URL hebben. Goede RESTful-architectuur definieert alleen zelfstandige bronnen, omdat het HTTP-protocol de set werkwoorden definieert die van toepassing is op die bronnen.

De andere suggestie is interessant, maar PUT suggereert dat je dan een GET kunt uitvoeren om een ​​representatie te krijgen van het ding dat je zojuist hebt geplaatst, wat niet heel veel oplevert zin in deze context.

Van wat je zegt, is er een aanzienlijk proces om het account van een gebruiker in of uit te schakelen en dat je het niet prettig vindt dat dit een PUT of PATCH operatie is om eenvoudigweg " zet een waarde om van waar naar false . Als dit enige tijd vergt, een overgangstoestand heeft en waarschijnlijk iets is dat u wilt blootstellen aan API-consumenten zodat zij zich bewust zijn van het proces, is het zinvol om het proces zelf als een soort hulpmiddel te definiëren:

Start deactivering:

POST api/members/deactivations

Krijg de huidige status van een deactivering of rapporteer over activiteiten die hebben plaatsgevonden:

GET api/members/deactivations/john.smith

Annuleer een deactivering die bezig is (optioneel):

DELETE api/members/deactivations/john.smith

Als u een account opnieuw kunt activeren, kan dit een vergelijkbaar patroon volgen.

Als u vindt dat er onvoldoende inhoud is om deze workflows te rechtvaardigen als hun eigen bronnen, of als u gewoon niet weet wat u moet antwoorden op GET , dan suggereert dit dat de werkstroom niet is zo belangrijk dat het niet zomaar voor de API-gebruikers kan worden verborgen en kan worden geactiveerd als neveneffect van het wijzigen van de actieve -waarde van de gebruiker.

3
toegevoegd
Het verschil is dat een deactivering duidelijk een "ding" is dat je onafhankelijk van andere bronnen kunt begrijpen, maar nog steeds sterk gerelateerd is aan leden .
toegevoegd de auteur Paul Turner, de bron
Ik denk dat, wat ik aanriep DisableMemberRequest , je deactivering aanroept. Ik vind het een goed idee om DELETE te gebruiken om het deactiveringsproces te annuleren. Maar nogmaals, dat is handig als uw deactivering een langlopend proces is.
toegevoegd de auteur Suhas, de bron

Zojuist een vergelijkbare vraag beantwoord in hier .

De praktische manier van denken of het toepassen van REST als uitgangspunt (het werkt tenminste voor mij) is om op de volgende manieren te denken:

1) Gebruik alleen HTTP 'GET/POST/PUT/DELETE' als manier om de acties van uw domein te modelleren. Net als wanneer u met een database werkt, worden al uw acties toegewezen aan CURD .

2) URI/URL is om bronnen alleen te identificeren. Mag nooit 'acties' in uw URI hebben.

3) De uitgewisselde gegevens moeten in de body van de HTTP-berichten staan. Gewoon om de discussies te vereenvoudigen, niet om in te gaan op het modelleren van de gegevens zelf

De oplossing van Tragedian ziet er schoon uit.

Bijgewerkt om @Suhas 'reacties te adresseren

REST gaat niet over het benoemen van conventies. Bij het ontwerpen van de REST API draait alles om het denken over de resources in plaats van 'actions'. Moet altijd denken aan 'Nonce' zoals resource in URL/URI. U hebt al alle CURD-acties waarvoor de domeinacties moeten worden toegewezen en om de bronnen in de URL te manipuleren.

Ik hou van de oplossing van Tragedian, alleen terwille van de discussie, we kunnen de oplossing van Tragedian refactiveren met een vergelijkbare set nonce en een ander URL-patroon om 'beter' bij het verschillende domeingebruik te passen. Het volgende is misschien niet de beste oplossing voor het domein, maar ze zijn equivalent RESTful.

Lidmaatschap verwijderen

  • VERWIJDEREN api/membership/[member-id]/

Krijg lidmaatschapsstatus

  • KRIJG api/lidmaatschap/[member-id]/status/

Voeg lidmaatschap toe

  • POST api/membership/[member-id]/

Bijgewerkt om het probleem met 'DisabledMember' als bron te verhelpen

Als u "PUT DisabledMember" gebruikt om 'member deactiveren' uit te voeren zoals voorgesteld door Suhas Wat zullen de volgende acties op de 'DisabledMember'-bron betekenen?

DELETE DisabledMember → activeer het opnieuw ??

POST DisabledMember -> ??

GET Disabled Member - dit is een gemakkelijke☺

Met dit ontwerp "camoufleert" het feitelijk de actie "uitschakelen" in de bron. Je kunt het nog steeds geforceerd dwingen om te doen wat je wilt, maar het zal niet zo Rustig voor mij zijn.

1
toegevoegd
Toen ik zei dat ik alleen 'om zakelijke redenen' bedoelde. Bijv. Als ik DELETE op DisabledMember verbreek, zou dit om zakelijke redenen zijn.
toegevoegd de auteur Suhas, de bron
Moet elke resource elke HTTP-actie ondersteunen? DELETE/POST op DisabledMember retourneert gewoon HTTP 405 niet toegestaan ​​
toegevoegd de auteur Suhas, de bron
Ik begrijp dat je ontwerpt op basis van bronnen. Maar ik zie geen commentaar op mijn derde ontwerp rond het introduceren van een nieuwe bron genaamd DisabledMember . Zijn er problemen met dat ontwerp?
toegevoegd de auteur Suhas, de bron
Ik denk dat het enige verschil tussen mijn tweede oplossing en de oplossing van de tragedie is - hij heeft een betere naamgevingsconventie.
toegevoegd de auteur Suhas, de bron
REST gaat niet over het benoemen van conventies. Bij het ontwerpen van de REST API draait alles om het denken over de resources in plaats van 'actions'. Moet altijd denken aan 'Nonce' zoals resource in URL/URI. U hebt al alle CURD-acties waarvoor de domeinacties moeten worden toegewezen en om de bronnen in de URL te manipuleren.
toegevoegd de auteur Ming Chan, de bron
Met 'DisabledMember'-ontwerp' verbergt 'het feitelijk de actie' uitschakelen 'in de resource. Je kunt het nog steeds geforceerd dwingen om te doen wat je wilt, maar het zal niet zo Rustig voor mij zijn.
toegevoegd de auteur Ming Chan, de bron
Het hoeft niet maar het zal meer zijn om zakelijke logica redenen; Als u bijvoorbeeld Verwijderen niet wilt toestaan, kan het zijn dat het niet is toegestaan ​​om deze specifieke bron te 'verwijderen' nadat deze is gemaakt. Ik denk meestal goed na over de naam van de bron door alle CURD-werkwoorden te gebruiken om mijn ontwerpkeuze te maken.
toegevoegd de auteur Ming Chan, de bron

Zojuist een vergelijkbare vraag beantwoord in hier .

De praktische manier van denken of het toepassen van REST als uitgangspunt (het werkt tenminste voor mij) is om op de volgende manieren te denken:

1) Gebruik alleen HTTP 'GET/POST/PUT/DELETE' als manier om de acties van uw domein te modelleren. Net als wanneer u met een database werkt, worden al uw acties toegewezen aan CURD .

2) URI/URL is om bronnen alleen te identificeren. Mag nooit 'acties' in uw URI hebben.

3) De uitgewisselde gegevens moeten in de body van de HTTP-berichten staan. Gewoon om de discussies te vereenvoudigen, niet om in te gaan op het modelleren van de gegevens zelf

De oplossing van Tragedian ziet er schoon uit.

Bijgewerkt om @Suhas 'reacties te adresseren

REST gaat niet over het benoemen van conventies. Bij het ontwerpen van de REST API draait alles om het denken over de resources in plaats van 'actions'. Moet altijd denken aan 'Nonce' zoals resource in URL/URI. U hebt al alle CURD-acties waarvoor de domeinacties moeten worden toegewezen en om de bronnen in de URL te manipuleren.

Ik hou van de oplossing van Tragedian, alleen terwille van de discussie, we kunnen de oplossing van Tragedian refactiveren met een vergelijkbare set nonce en een ander URL-patroon om 'beter' bij het verschillende domeingebruik te passen. Het volgende is misschien niet de beste oplossing voor het domein, maar ze zijn equivalent RESTful.

Lidmaatschap verwijderen

  • VERWIJDEREN api/membership/[member-id]/

Krijg lidmaatschapsstatus

  • KRIJG api/lidmaatschap/[member-id]/status/

Voeg lidmaatschap toe

  • POST api/membership/[member-id]/

Bijgewerkt om het probleem met 'DisabledMember' als bron te verhelpen

Als u "PUT DisabledMember" gebruikt om 'member deactiveren' uit te voeren zoals voorgesteld door Suhas Wat zullen de volgende acties op de 'DisabledMember'-bron betekenen?

DELETE DisabledMember → activeer het opnieuw ??

POST DisabledMember -> ??

GET Disabled Member - dit is een gemakkelijke☺

Met dit ontwerp "camoufleert" het feitelijk de actie "uitschakelen" in de bron. Je kunt het nog steeds geforceerd dwingen om te doen wat je wilt, maar het zal niet zo Rustig voor mij zijn.

1
toegevoegd
Toen ik zei dat ik alleen 'om zakelijke redenen' bedoelde. Bijv. Als ik DELETE op DisabledMember verbreek, zou dit om zakelijke redenen zijn.
toegevoegd de auteur Suhas, de bron
Moet elke resource elke HTTP-actie ondersteunen? DELETE/POST op DisabledMember retourneert gewoon HTTP 405 niet toegestaan ​​
toegevoegd de auteur Suhas, de bron
Ik begrijp dat je ontwerpt op basis van bronnen. Maar ik zie geen commentaar op mijn derde ontwerp rond het introduceren van een nieuwe bron genaamd DisabledMember . Zijn er problemen met dat ontwerp?
toegevoegd de auteur Suhas, de bron
Ik denk dat het enige verschil tussen mijn tweede oplossing en de oplossing van de tragedie is - hij heeft een betere naamgevingsconventie.
toegevoegd de auteur Suhas, de bron
REST gaat niet over het benoemen van conventies. Bij het ontwerpen van de REST API draait alles om het denken over de resources in plaats van 'actions'. Moet altijd denken aan 'Nonce' zoals resource in URL/URI. U hebt al alle CURD-acties waarvoor de domeinacties moeten worden toegewezen en om de bronnen in de URL te manipuleren.
toegevoegd de auteur Ming Chan, de bron
Met 'DisabledMember'-ontwerp' verbergt 'het feitelijk de actie' uitschakelen 'in de resource. Je kunt het nog steeds geforceerd dwingen om te doen wat je wilt, maar het zal niet zo Rustig voor mij zijn.
toegevoegd de auteur Ming Chan, de bron
Het hoeft niet maar het zal meer zijn om zakelijke logica redenen; Als u bijvoorbeeld Verwijderen niet wilt toestaan, kan het zijn dat het niet is toegestaan ​​om deze specifieke bron te 'verwijderen' nadat deze is gemaakt. Ik denk meestal goed na over de naam van de bron door alle CURD-werkwoorden te gebruiken om mijn ontwerpkeuze te maken.
toegevoegd de auteur Ming Chan, de bron

Lid heeft de status Actief en Uitgeschakeld

De status is dus een eigenschap van de entiteit/resource van het lid; Waarom zou je in dat geval niet gewoon de PUT-methode op Member-resource willen gebruiken met status ingesteld op Disabled?

0
toegevoegd
Lid heeft veel andere velden die klanten mogelijk willen bijwerken. Ze gebruiken in die situatie. Deze updates hebben meestal niet tot gevolg dat een andere workflow wordt geactiveerd. Het zijn eenvoudige updates voor onze gegevensopslag. Het uitschakelen van een lid is echter een complexe werkstroom en moet als zodanig worden gescheiden van de ledenupdate als een concept.
toegevoegd de auteur Suhas, de bron
Bedoel je een zoekopdrachtstring? Ik betwijfel of ik query-strings zou gebruiken op post om parameters in te sturen. En een bericht om ze allemaal te regeren lijkt mij een schending van SRP.
toegevoegd de auteur Suhas, de bron
je hebt een bron onder leden/{someId}. U gebruikt GET voor het ophalen van die resource, DELETE - voor het verwijderen van die resource, PUT - voor het bijwerken van die resource. De POST-methode is gratis, dus je kunt deze gebruiken om het deactiveren van je lid te activeren
toegevoegd de auteur maks, de bron
als u verschillende gevallen van startend workflowproces hebt, kan dat worden geïdentificeerd aan de hand van verschillende parameters in de POST-methode
toegevoegd de auteur maks, de bron

Lid heeft de status Actief en Uitgeschakeld

De status is dus een eigenschap van de entiteit/resource van het lid; Waarom zou je in dat geval niet gewoon de PUT-methode op Member-resource willen gebruiken met status ingesteld op Disabled?

0
toegevoegd
Lid heeft veel andere velden die klanten mogelijk willen bijwerken. Ze gebruiken in die situatie. Deze updates hebben meestal niet tot gevolg dat een andere workflow wordt geactiveerd. Het zijn eenvoudige updates voor onze gegevensopslag. Het uitschakelen van een lid is echter een complexe werkstroom en moet als zodanig worden gescheiden van de ledenupdate als een concept.
toegevoegd de auteur Suhas, de bron
Bedoel je een zoekopdrachtstring? Ik betwijfel of ik query-strings zou gebruiken op post om parameters in te sturen. En een bericht om ze allemaal te regeren lijkt mij een schending van SRP.
toegevoegd de auteur Suhas, de bron
je hebt een bron onder leden/{someId}. U gebruikt GET voor het ophalen van die resource, DELETE - voor het verwijderen van die resource, PUT - voor het bijwerken van die resource. De POST-methode is gratis, dus je kunt deze gebruiken om het deactiveren van je lid te activeren
toegevoegd de auteur maks, de bron
als u verschillende gevallen van startend workflowproces hebt, kan dat worden geïdentificeerd aan de hand van verschillende parameters in de POST-methode
toegevoegd de auteur maks, de bron

Als het een kort proces is om de gebruiker uit te schakelen, waarom dan niet HTTP-PATCH gebruiken?

Zie dit antwoord op een vergelijkbare vraag

0
toegevoegd
Ik heb details aan de vragen toegevoegd. Het uitschakelen van een lid is geen eenvoudige update.
toegevoegd de auteur Suhas, de bron