21

RESTfulなWebサービスで、主キーが他のもののコンポジットであるリソースに対してCRUD操作を実行するための通常の標準または習慣に関する情報を見つけることができない問題が発生しましたリソースID。 MVC WebApiを使用してコントローラを作成しています。複合キーリソースRESTサービス

  • Product:PK =のProductId
  • Part:PK = PartId
  • ProductPartAssoc:PK =(のProductId、PartId)

製品を持つことができ、多くの例では、3つのテーブルを持っています部品および部品は、多くの製品の構成要素となり得る。アソシエーションテーブルには、アソシエーション自体に関連する追加情報も編集可能な情報が含まれています。

私たちのように定義されたルートのテンプレートを使用して通常のGET/PUT/POST/DELETE操作ハンドルProductsControllerPartsControllerのクラスがあります。次のIRIが動作することを{controller}/{id}/{action}は、このような:

  • GET、POST /api/Productsは - すべての製品を返します、新製品
  • GET、PUTを作成し、/api/Products/1 DELETE - 、すべての部品を返し、新しい部分
  • を作成 - 取り出し/更新を/製品1
  • GET、POST /api/Partsが削除
  • GET、PUT、/api/Parts/2 DELETE - 製品1
  • のためのすべての部品が/api/Parts/2/Productsをゲット - - パート2成分

されているすべての製品を得る取り出し/更新を/パート2

  • /api/Products/1/PartsをGET削除ProductPartAssocリソースのルートテンプレートを定義する方法に問題があります。アソシエーションデータを取得するためにルートテンプレートとIRIの外観はどうでしょうか? 慣例を遵守、私が何か期待する:

    • GET、POST /api/ProductPartAssocは - 、すべての関連付けを返す関連
    • GET、PUTを作成し、/api/ProductPartAssoc/[1,2] DELETE - 取り出し/更新を/製品1とパートの間の関連付けを削除します2

    私の同僚は、しかし、これは審美的に不愉快見つけて、すべてでProductPartAssocControllerクラスを持たない方が良いことだと思うのではなく、関連データを管理するためにProductsControllerにメソッドを追加するように見える:

    • GET、PUTは、/api/Products/1/Parts/2削除 - 従来、/Book/5/Chapter/3のような他の実施例に基づく場合である部分1の部材としてのパート2の製品1及び2部ではなく、データ間の関連付けのためのデータを取得します私は他の場所で見たことがある。
    • POSTここでIRIがどのように見えると思っているのかわかりません。残念ながら、彼らは意思決定者です。

    私が求めているのは、私が指し示すことができる妥当性や方向性のいずれかであると私は推測しています。「これは他の人のことです。

    コンポジットキーで識別されるリソースを処理する典型的な方法は何ですか?

  • +1

    エンティティをリンクする場合、Odataサービスに指定するODataプロトコルのように、uriスペースをモデル化できます。私はODataサービスを実装することを提案していませんが、有用な洞察を提供し、あなたの問題に近いので、それを検討する価値があります。エンティティ間のリンクを管理するにはこちらをご覧ください:http://www.odata。org/documentation/odata-v2-documentation/operations /#29_Manipulating_Links –

    +0

    ProductPartAssocの外観は何ですか?そして、それがサポートしているCRUD操作は何ですか? –

    +0

    この例は任意ですが、ProductPartAssocクラスは次のように見えます(ここでは簡潔に限られたスペースには申し訳ありません):class ProductPartAssoc {int ProductId; int PartId; int amountUsed; decimal assemblyCost; int installerId; } 4つのCRUD操作(Create、Retrieve、Update、Delete)をすべてサポートする必要があります。 – Mitselplik

    答えて

    17

    私も/api/Products/1/Parts/2という美学が好きです。同じアクションに複数のルートを設定することもできますので、同じリソースに対して別のURLとして/api/Parts/2/Products/1を提供することもできます。

    POSTに関しては、既にコンポジットキーを知っています。では、POSTの必要性をなくし、作成と更新の両方にPUTを使用するだけの理由は何ですか?あなたのシステムがプライマリキーを生成する場合、コレクションリソースURLへのPOSTは素晴らしいですが、既知のプライマリキーのコンポジットを持っている場合、なぜPOSTが必要ですか?

    私はまた、別のProductPartAssocControllerにこれらのURLのアクションを含めるという考えが好きです。あなたはカスタムルートマッピングをしなくてはならないでしょうが、非常に簡単なAttributeRouting.NETのようなものを使用しているのならば。

    たとえば、私たちは役割でユーザーを管理するための次の操作を行います。

    PUT, GET, DELETE /api/users/1/roles/2 
    PUT, GET, DELETE /api/roles/2/users/1 
    

    6 URLのが、すべてのGrantsControllerで唯一の3アクションは、(我々はユーザーとロール「グラント」の間に動名詞を呼び出します)。クラスはAttributeRouting.NETを使用して、このような何かを探して終わる:

    [RoutePrefix("api")] 
    [Authorize(Roles = RoleName.RoleGrantors)] 
    public class GrantsController : ApiController 
    { 
        [PUT("users/{userId}/roles/{roleId}", ActionPrecedence = 1)] 
        [PUT("roles/{roleId}/users/{userId}", ActionPrecedence = 2)] 
        public HttpResponseMessage PutInRole(int userId, int roleId) 
        { 
         ... 
        } 
    
        [DELETE("users/{userId}/roles/{roleId}", ActionPrecedence = 1)] 
        [DELETE("roles/{roleId}/users/{userId}", ActionPrecedence = 2)] 
        public HttpResponseMessage DeleteFromRole(int userId, int roleId) 
        { 
         ... 
        } 
    
        ...etc 
    } 
    

    これは私にはかなり直感的なアプローチです。独立したコントローラにアクションを保持することは、よりリーンなコントローラにもなります。

    +1

    洞察のおかげで:-) 2つのこと:(1)AttributeRouting.Netのヒント - 素晴らしいものをありがとう。 (2)振り返ってみると、あなたはPOST操作を必要としないことについて正しいです。それを指摘してくれてありがとう。私は私の質問に答えるあなたの答えをマーク... – Mitselplik

    0

    私はお勧め:

    • POST /api/PartsProductsAssocを:部品と製品の間のリンクを作成します。 POSTデータに部品IDと製品IDを組み込みます。
    • /api/PartsProductsAssoc/<assoc_id><assoc_id>との読取り/更新/削除リンク(部品または製品IDではない、はい、これはPartsProductsAssocテーブルに新しい列を作成することを意味します)。
    • GET /api/PartsProductsAssoc/Parts/<part_id>/Products:指定された部分に関連付けられた製品のリストを取得します。
    • GET /api/PartsProductsAssoc/Products/<product_id>/Parts:特定の製品に関連付けられている部品のリストを取得します。

      • シングル、完全修飾URIリンクごと:

      理由は、このアプローチを取ります。

    • リンクを変更すると、単一のRESTリソースが変更されます。

    詳細については、https://www.youtube.com/watch?v=hdSrT4yjS1g(56:30)を参照してください。