Mevcut bir öğeyi REST API'sindeki bir koleksiyona eklemek için en iyi kalıp hangisidir?


23

Pragmatik bir REST API tasarlıyorum ve bir koleksiyona mevcut varlıkları nasıl en iyi şekilde ekleyeceğime biraz şaşırdım. Etki alanı modelim, Siteler koleksiyonuna sahip bir Proje içeriyor. Bu katı bir çoktan çoğa ilişkidir ve ilişkiyi açıkça modelleyen bir varlık yaratmaya ihtiyacım yok (yani ProjectSite).

API’m, tüketicilerin bir Projeye varolan bir Site eklemelerine izin verecek. Telefonu kapattığımda, gerçekten ihtiyacım olan tek veri ProjectId ve SiteId. İlk fikrim şuydu:

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

Ama ben de düşündüm

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

JSON içeriği olarak gönderilen bir Site varlığı ile.

Seçenek 1 basit ve işe yarıyor ama pek doğru gelmiyor ve bu modeli izleyemeyen başka ilişkilerim var, böylece API'ma tutarsızlık katar.

Seçenek 2 daha iyi hissediyor ancak iki endişeye yol açıyor:

  • Yeni bir Site gönderilirse, bir Site oluşturmalı mıyım veya bir istisna atmalı mıyım (SiteId = 0)?
  • İlişkiyi oluşturmak için yalnızca ProjectId ve SiteId'ye ihtiyaç duyduğum için, Site diğer mülkler için yanlış veya eksik verilerle birlikte yayınlanabilir.

Üçüncü seçenek, yalnızca ilişkiyi oluşturmak ve silmek için basit bir uç nokta sağlamaktır. Bu son nokta, yalnızca ProjectId ve SiteId içeren bir JSON yükünü bekler.

Ne düşünüyorsun?



@RoryHunter Bu bağlantıda bazı ilginç tartışmalar var ancak belirsizliğimi ortadan kaldıran hiçbir şey yok. Özellikle kabul edilen cevabın “Doğru anladığını” belirtmesi hoşuma gidiyor. ve 2. sıra (büyük bir marjla da olsa) cevabı "Basitçe söylemek gerekirse, bunu tamamen geriye doğru yapıyorsunuz."
Jamie Ide

Müşteri, koleksiyona eklenen kimliği kontrol ettiği için POST yerine PUT kullanacağım için ilk seçeneğiniz gayet iyi. 2. seçenekle ilgili ilk endişeniz tamamen size kalmış, yeni siteler istemiyorsanız bir istisna atmayın, 4xx kodlarından birini geri gönderin. İkinci kaygınız ne burada ne de orada. Eklemeye izin vermediğiniz sürece, zaten bir Sitenin tamamını göndermemelisiniz. Mevcut bir siteyi eklemek, kimliği yalnızca siteyi değiştirirken değil, yalnızca "ProjectSite" koleksiyonunu da oluşturmalıdır (bunun için ayrı bir kaynak oluşturmasanız bile).
Marjan Venema

Yanıtlar:


14

POST "ekleme" fiili ve ayrıca "işleme" fiilidir. PUT, "yarat / güncelle" fiilidir (bilinen tanımlayıcılar için) ve tam hedef URI bilindiği için burada doğru seçim gibi görünüyor. projectIdve siteIdzaten var, yeni bir kimlik oluşturmak için "bir koleksiyona POST" uygulamanıza gerek yok.

PUT ile ilgili sorun, bedenin PUTting yaptığınız kaynağın temsili olmasını gerektirmesidir. Ancak buradaki amaç, Site kaynağını güncellemek yerine "proje / siteler" toplama kaynağına eklemektir.

Birisi mevcut bir Sitenin tam bir JSON temsilcisini koyarsa? Eğer güncelleştirmek Should ve nesneyi güncellemek? Bunu destekleyebilirsin, ama sanki niyet değil gibi geliyor. Dediğin gibi,

Gerçekten ihtiyacım olan tek veri ProjectId ve SiteId.

Aksine, siteIdkoleksiyona POST göndermeyi dener ve POST'un "ekleme" ve "işlem" niteliğine güvenirim:

POST myapi / projeler / {projectId} / sites

{'id': '...'}

Eğer siteler değiştiriyorsanız yana toplama kaynağı değil Sitesi kaynak , istediğin URI var. POST "ekleme / işlemeyi" bilir ve bu kimliğe sahip öğeyi projenin siteler koleksiyonuna ekler.

Bu, hala JSON'u parçalayarak ve kimliği atlayarak proje için yepyeni siteler oluşturmaya kapıyı açık bırakıyor. "Kimlik yok" == "sıfırdan oluştur". Ancak, URI koleksiyonu bir kimlik alır ve başka bir şey almazsa, ne olması gerektiği çok açık.

İlginç soru. :)


POST'un yaratma için olduğuna ve PUT'un güncelleme için olduğuna inandığına inanıyorum, ancak sonucunuz dün sona erdiğim yerde. İşin güzel yanı, Web API'sındaki öznitelik yönlendirme sayesinde, kodun ProjectSites denetleyicide olması ve kodun iyi düzenlenmesidir.
Jamie Ide

Sana kullanmak gerekir tanımlayan nedeni düşünmek POSTyerine PUTya PATCHburada tamamını yok olmasıdır Sitekoymak için varlık siteskaynağı. Yalnızca koleksiyona eklemesi için işlem yapılmasını gerektiren bir kimliğiniz vardır.
ezmek

4

Bu gibi şeyler için Patchyöntemi kullanıyoruz . Yapmak istediğiniz, bir Site eklemek için mevcut bir Projeyi değiştirmek.

Yani böyle bir şey işe yarayacak

PATCH myapi/projects/{id} 

İstek gövdesinde Site (ler) i JSON / JSONArray olarak.

Bu şekilde, gerektiğinde Projenin farklı kısımlarını değiştirmek için aynı URL’yi kullanabilirsiniz - uygulamadaki kodunuz kaynağın bu kısmi değişimini gerçekleştirebilecek kadar akıllı olmalıdır.


İlginç yaklaşım "Zengin" (yani oldukça bağımlı) bir eski alan modelim var ve Proje'nin özellikle asılı birçok koleksiyonu var. Talepte bulunan varlık tipini tespit etmek zor olacak ve benim pragmatik hedefime uymuyor.
Jamie Ide

Neden bir meydan okuma? Bu kısıtlamalara sahipseniz, ne gönderdiğini açıkça belirten bir JSON kullanabilirsiniz ... gibi {"sites": [], "other-stuff": {}}, daha sonra tüm bu "subjsons" ları kolayca işlemek için kodunuzu dallandırabilirsiniz. Bu gerçekten sizin özel probleminize bağlı, ama yine de bu tarz şeyler için tasarlandığı gibi PATCH'i kullanmanızı tavsiye ederim.
juan

Gördüğüm olumsuz taraflar 1) API, hangi koleksiyonların değişikliklere izin verdiğini açıkça belirtmiyor; 2) Web API parametresi bağlamasını kaldıramadı; 3) büyük anahtar veya if ifadesi.
Jamie Ide

Başka bir yerde kullanılan yama yöntemini hiç görmedim
NimChimpsky

Olmaz PATCHda tam varlık yerine bir kimlik yerine, burada değer olarak geçirilecek bekler bazı varlığa işaret ettiği?
ezmek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.