既存のアイテムをREST APIのコレクションに追加するための最適なパターンは何ですか?


23

私は実用的なREST APIを設計していますが、既存のエンティティをコレクションに追加する最善の方法に少し立ち往生しています。私のドメインモデルには、サイトのコレクションを持つプロジェクトが含まれています。これは厳密な多対多の関係であり、関係を明示的にモデル化するエンティティ(ProjectSiteなど)を作成する必要はありません。

私のAPIにより、消費者は既存のサイトをプロジェクトに追加できます。ハングアップしているのは、本当に必要なデータはProjectIdとSiteIdだけだということです。私の最初のアイデアは:

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

しかし、私も考えました

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

JSONコンテンツとして送信されるSiteエンティティを使用します。

オプション1はシンプルで機能しますが、あまり適切ではないため、このパターンに従うことができない他の関係があるため、APIに矛盾が生じます。

オプション2は良い感じですが、2つの懸念につながります。

  • 新しいサイトが投稿された場​​合(SiteId = 0)、サイトを作成するか、例外をスローする必要がありますか?
  • 関係を作成するためにProjectIdとSiteIdのみが必要なため、他のプロパティのデータが間違っているか、欠落しているサイトが投稿される可能性があります。

3番目のオプションは、関係を作成および削除するためだけに単純なエンドポイントを提供することです。このエンドポイントでは、ProjectIdとSiteIdのみを含むJSONペイロードが必要です。

どう思いますか?



@RoryHunterそのリンクには興味深い議論がいくつかありますが、私の不確実性を排除するものはありません。私は特に、受け入れられた答えが「あなたは正しく理解した」と述べているのが好きです。2位(とはいえ大きなマージン)は、「簡単に言えば、これを完全に後回しにしている」と答えます。
ジェイミー

クライアントがコレクションに追加されるIDを制御しているため、POSTではなくPUTを使用しますが、最初のオプションは問題ありません。オプション2の最初の懸念は完全にあなた次第です。新しいサイトが必要ない場合は、例外をスローせずに4xxコードの1つを返します。あなたの2番目の懸念はここにもそこにもありません。追加を許可しない限り、サイト全体を投稿しないでください。既存のサイトを追加すると、サイトを変更するときにのみIDを持ち、「ProjectSite」コレクションのみを持つ必要があります(そのための別個のリソースを作成しなくても)。
マルジャンヴェネ

回答:


14

POSTは「追加」動詞であり、「処理」動詞でもあります。PUTは「作成/更新」動詞(既知の識別子用)であり、完全なターゲットURIが既知であるため、ここではほとんど正しい選択のように見えます。projectIdそしてsiteIdあなたは、新しいIDを生成するために、「コレクションにPOST」する必要はありませんので、すでに存在しています。

PUTの問題は、PUTしているリソースの本体を本体にする必要があることです。ただし、ここでの目的は、サイトリソースを更新するのではなく、「プロジェクト/サイト」コレクションリソースに追加することです。

誰かが既存のサイトの完全なJSON表現をPUTした場合はどうなりますか?コレクション更新し、オブジェクトを更新する必要がありますか?それをサポートすることはできますが、それは意図ではないようです。あなたが言ったように、

本当に必要なデータはProjectIdとSiteIdだけです

むしろ、siteIdコレクションにPOSTを試みて、POSTの「追加」および「プロセス」の性質に依存します。

POST myapi / projects / {projectId} / sites

{'id': '...'}

Site リソースではなく、サイトコレクションリソースを変更しているので、それが必要なURIです。POSTは「追加/処理」を認識し、そのIDを持つ要素をプロジェクトのサイトコレクションに追加できます。

JSONを具体化し、IDを省略することにより、プロジェクトの新しいサイトを作成するための扉が開かれたままです。「IDなし」==「ゼロから作成」。しかし、コレクションURIがIDを取得し、それ以外の何も取得しない場合、何が起こる必要があるかはかなり明確です。

興味深い質問。:)


私は、POSTは作成用であり、PUTは更新用であると信じていますが、あなたの結論は昨日終わりました。良い点は、Web APIの属性ルーティングのおかげで、ProjectSitesコントローラーにコードがあるため、コードが適切に編成されていることです。
ジェイミー

POST代わりに、PUTまたはPATCHここで使用する必要がある決定的な理由はSitesitesリソースに入れるエンティティ全体がないためだと思います。IDのみがあり、コレクションに追加するには処理が必要です。
クラッシュ

4

このようなPatch方法でメソッドを使用します。やりたいことは、既存のプロジェクトを変更して、サイトを追加することです。

だからこのようなものはうまくいくでしょう

PATCH myapi/projects/{id} 

リクエスト本文にJSON / JSONArrayとしてサイトエンティティを含めます。

そうすれば、必要に応じて同じURLを使用してプロジェクトのさまざまな部分を変更できます。実装のコードは、リソースのこの部分的な変更を処理するのに十分インテリジェントでなければなりません。


興味深いアプローチ。「リッチ」(つまり、依存度の高い)古いドメインモデルがあり、Projectには特に多くのコレクションがあります。リクエストに含まれるエンティティタイプを検出することは難題であり、私の実用的な目標には適合しません。
ジェイミー

なぜ挑戦なのか?これらの制限がある場合は、送信するものを明示するJSONをいつでも使用{"sites": [], "other-stuff": {}}できます。たとえば、コードを分岐させて、これらすべての「サブジョン」を非常に簡単に処理できます。それは本当にあなたの特定の問題に依存しますが、この種のことのために特別に設計されたPATCHの使用をお勧めします。
フアン14年

私が見る欠点は、1)APIはどのコレクションが変更を許可するかを明示的に伝えません。2)Web APIパラメーターバインディングを活用できません。3)大きなスイッチまたはifステートメント。
ジェイミーイド14年

私はどこにも使用されたパッチ法見たことがない
NimChimpsky

PATCHまた、あるエンティティを指すidではなく、完全なエンティティがその値としてここに渡されることを期待しませんか?
クラッシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.