Який найкращий зразок для додавання наявного елемента до колекції в API REST?


23

Я розробляю прагматичний API REST, і я трохи застряг у тому, як найкраще додати існуючі сукупності до колекції. Моя модель домену включає проект, який має колекцію Сайтів. Це суворий зв'язок між багатьма і багатьма, і мені не потрібно створювати сутність, яка явно моделює відносини (тобто ProjectSite).

Мій API дозволить споживачам додати існуючий сайт до проекту. Де я зависаю, це те, що мені потрібні єдині дані ProjectId та SiteId. Моя початкова ідея:

1. POST myapi/projects/{projectId}/sites/{siteId}

Але я теж подумав

2. POST myapi/projects/{projectId}/sites

із об'єктом сайту, надісланим як вміст JSON.

Варіант 1 простий і працює, але не дуже добре, і у мене є інші стосунки, які не можуть слідувати цій схемі, тому це додає непослідовність мого API.

Варіант 2 відчуває себе краще, але призводить до двох проблем:

  • Чи слід створити Сайт або викинути виняток, якщо розміщено новий Сайт (SiteId = 0)?
  • Оскільки мені потрібні лише ProjectId і SiteId для створення взаємозв'язку, Сайт може бути розміщений з неправильними або відсутніми даними для інших ресурсів.

Третій варіант - надання простої кінцевої точки виключно для створення та видалення відносин. Ця кінцева точка очікувала б корисну навантаження JSON, що містить лише ProjectId та SiteId.

Як ти гадаєш?



@RoryHunter У цьому посиланні є якась цікава дискусія, але нічого, що усуває мою невизначеність. Мені особливо подобається, що у прийнятій відповіді зазначено "Ви зрозуміли правильно". а 2-е місце (хоч і з великим відривом) відповідає "Простіше кажучи, ви робите це повністю назад".
— Джеймі Іде

Ваш перший варіант прекрасний, хоча я б використовував PUT замість POST, оскільки клієнт контролює особу, яка додається до колекції. Ваша перша стурбованість варіантом 2 повністю залежить від вас, якщо ви не хочете нових сайтів, не кидайте винятків, але поверніть один із 4xx-кодів. Ваша друга турбота - ні тут, ні там. Ви все одно не повинні публікувати весь веб-сайт, якщо ви не допускаєте доповнень. Додавання існуючого сайту має мати ідентифікатор лише під час зміни сайту, але лише колекцію "ProjectSite" (навіть якщо ви не створите для нього окремого ресурсу).
— Мар'ян Венема

Відповіді:


14

POST - дієслово "додавати", а також дієслово "обробляти". PUT - дієслово "create / update" (для відомих ідентифікаторів), і майже виглядає як правильний вибір, тому що повний цільовий URI відомий. projectIdі siteIdвже існують, тож вам не потрібно "POST на колекцію", щоб створити новий ідентифікатор.

Проблема з PUT полягає в тому, що він вимагає, щоб тіло було представлення ресурсу, який ви PUTING. Але тут наміром є додавання до ресурсу колекції "проект / сайти", а не оновлення ресурсу Сайту.

Що робити, якщо хтось ПОДАЄ повне представлення наявного Сайту JSON? Чи слід оновити колекцію та оновити об’єкт? Ви можете це підтримати, але це здається, що це не є наміром. Як ти сказав,

єдині мені потрібні дані ProjectId та SiteId

Швидше я б спробував розмістити siteIdколекцію до колекції і покластися на "додавання" та "процес" характеру POST:

POST myapi / Проекти / {projectId} / сайти

{'id': '...'}

Оскільки ви змінюєте ресурс колекції сайтів, а не ресурс Сайту , це потрібний URI. POST може знати "додавання / обробку" та додавання елемента з цим ідентифікатором до колекції сайтів проекту.

Це все ще залишає двері відкритими для створення абсолютно нових сайтів для проекту, розбиваючи JSON і опускаючи ідентифікатор. "Без ідентифікатора" == "створити з нуля". Але якщо URI колекції отримує ідентифікатор і нічого іншого, то цілком зрозуміло, що має відбутися.

Цікаве запитання. :)


Я вірю, що вважаю, що POST призначений для створення, а PUT - для оновлення, але ваш висновок - це те, де я закінчився вчора. Приємно те, що завдяки маршрутизації атрибутів у веб-API я маю код у контролері ProjectSites, тому код добре організований.
— Джеймі Іде

Я думаю , що визначення причин ви повинні використовувати POSTзамість PUTабо в PATCHтому , що ви не маєте весь Siteоб'єкт , щоб помістити в sitesресурс. У вас є лише ідентифікатор, який вимагає його обробки, щоб додати його до колекції.
— розчавити

4

Ми використовуємо Patchметод для подібних речей. Що ви хочете зробити - це змінити існуючий проект, щоб додати його до нього.

Тож щось подібне спрацювало б

PATCH myapi/projects/{id} 

з об'єктом сайтів (сайтів) як JSON / JSONArray в органі запиту.

Таким чином, ви можете використовувати одну і ту ж URL-адресу для зміни різних частин Проекту, якщо вам потрібно - ваш код при реалізації повинен бути досить розумним, щоб обробляти цю часткову модифікацію ресурсу.


Цікавий підхід. У мене є "багата" (тобто сильно залежна) старша модель домену, і Project особливо має безліч колекцій, що висять її. Виявлення типу юридичної особи, що знаходиться у запиті, було б викликом і не відповідало моїй прагматичній цілі.
— Джеймі Іде

Чому виклик? Якщо у вас є ці обмеження, ви завжди можете використовувати JSON, який робить явне те, що він надсилає ... як {"sites": [], "other-stuff": {}}, ви можете потім розгалужити свій код, щоб дуже легко обробляти всі ці "підмайстри". Це дійсно залежить від вашої конкретної проблеми, але я все-таки рекомендую використовувати PATCH, оскільки він розроблений спеціально для подібних речей.
— хуан

Мінуси, які я бачу, такі: 1) API не повідомляє прямо, які колекції дозволяють змінювати; 2) не може використовувати прив'язку параметрів Web API; 3) великий перемикач або оператор if.
— Джеймі Іде

Я ніколи не бачив методу виправлення, який використовував ніде більше
— NimChimpsky

Чи не PATCHочікуєте також, що тут буде передано повне ціле як його значення, а не ідентифікатор, який вказує на якусь сутність?
— розчавити
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.