6

ASP.net Web API の背後には、コード ファーストのエンティティ フレームワーク モデルがあります。次の (簡略化された) エンティティを検討してください。

public class Form
{
    public long Id { get; set; }

    public string Identifier { get; set; }

    public virtual FormGroup Group { get; set; }
}

public class FormGroup
{
    public long Id { get; set; }

    public string Identifier { get; set; }

    public virtual ICollection<Form> Forms { get; set; }
}

ご覧のとおり、FormGroups と Forms の間には 1 対多の関係があります。私の質問は、フォームが属するグループを変更できる RESTful API をどのように設計すればよいですか?

これまでのところ、それぞれに長所と短所がある 2 つの潜在的なアプローチを考え出しました。

関係をリンク構造として表す:

{
    "Id" : 1,
    "Identifier" : "Form1",
    "link" : {
        "rel": "http://myapi/res/formgroup",
        "href": "http://myapi/formgroups/1"
    }
}

長所:

  • フォームグループ表現への意味のあるリンクが含まれています

短所:

  • そのようなリンクには特定の基準はありません
  • サーバー側のロジックがより複雑になる

PUT を使用してリソースをリンクする

data: {
    "Id" : 1,
    "Identifier" : "Form1"
}

PUT data to http://myapi/formgroups/1/forms

長所:

  • 表現に余分なプロパティはありません

短所:

  • リソースは、複数の URI (/forms/1 と /formgroups/1/forms/1 など) で識別できます。
  • キーを形成するために必要なデータ以外のデータを送信することは、無関係であるか、混乱を招きます。

これらのアプローチには、それぞれ長所よりも短所があるように見えるため、特に満足しているとは言えません。

「適切な」解決策は、DTO を実装し、リソース表現からエンティティ モデルを分離することです。これにより、設定できる FormGroupId を追加できます。

すべての優れたプログラマーと同様に、RESTful API でこれがどのように機能するかを知りたいと思っています。また、モデル内の任意のナビゲーション プロパティに一般的に適用できるソリューションも必要です。

はがきの回答...これらのアプローチのいずれかが有効ですか、それとも私が見逃した別の方法がありますか?

ピート

4

2 に答える 2

2

データ モデルに基づいて API を構築すると、全体的な設計が制限されるだけです。私は自分の表現から戻って作業する傾向があります。

表現を完全に制御することで、思いのままに関係を表現できます。たとえば、自分の表現内に自分の表現を含めることを決定できますFormGroupForm

GET /api/forms/1

    {
      "Id" : 1,
      "Name" : "Form 1",
      "FormGroup" : {
        "Id" : 1,
        "Name" : "Form Group 1"
      }
    }

FormGroupまたは、表現にフォームを含めます。

GET /api/formgroups/1

    {
      "Id" : 1,
      "Name" : "Form Group 1",
      "Forms" : [
        {
          "Id" : 1,
          "Name" : "Form 1"
        },
        {
          "Id" : 2,
          "Name" : "Form 2"
        }
      ]
    }

実際、両方を行うことができます。各リソースの URI 識別子が 1 つだけであることを確認してください。

本当に REST を採用し、API 応答にハイパーメディア リンクを含めたい場合は、Hypertext Application Language (HAL) をチェックすることをお勧めします。HAL は、リソース間の関連リンクを表現するための規則を提供します。例えば:

{
  "_links" : {
    "self" : { "href" : "/api/forms/1" },
    "related" : { "href" : "/api/formgroups/1" }
  }
  "Id" : 1,
  "Name" : "Form 1",
  "FormGroupId" : 1
}

リソースをどのように表現するかによって、リソース間の関係を管理する方法が決まるわけではないことを理解していただければ幸いです。

これをどのように行うかは、シナリオで何が論理的であるかに大きく依存する必要があり、多くの場合、誰が関係を所有しているかを決定することによって助けられます.

典型的なBlog Post .* Comments例を挙げてみましょう。コメント自体にはほとんど意味がありません。ブログのコメントを管理するための API を設計する場合、次のようにします。

POST   /posts/1/comments  - Add a comment to post 1
DELETE /posts/1/comments/1 - Remove comment 1 from post 1

コメントにはアイデンティティがありますが、ブログ投稿のコンテキスト内でのみであることに注意してください。

あなたの場合 (Twitter での議論に基づいて) FormsFormGroup. また、孤立したフォーム、つまりグループに属さないフォームを持つことができるとも言いました。

これを念頭に置いて、リソースFormGroupを介して関係を管理することは理にかなっています。最も簡単な方法は、フォーム リソースに対して POST または PUT を実行するときにプロパティをForm設定/更新することです。FormGroupId(これもシナリオによって異なります)、リソースFormGroupの他のプロパティを更新せずに を変更する機能が必要なForm場合は、PATCH を送信するか、関係を管理するための「サブリソース」を作成します。

POST /api/forms/1/group -- set the form group for forms/1
{
  "formGroupId" : 10
}

DELETE /api/forms/1/group -- unlink forms/1 from its group

残念ながら、リソース間の関係を表す「正しい方法」はありません。私のアドバイスは、最も自然に感じるものを選ぶことです.

于 2013-02-06T22:15:58.970 に答える
1

あなたが正しいです。現在、ASP.NET Web API のリソースの世界は、リソースの関係を管理して別の場所にリンクする必要がある一方で、どこかでルートを定義するという混合の世界です。各ルートを独自に定義することで、階層的なルーティングを行うことができます。これには、メンテナンスとパフォーマンスの影響があります。

これらをまとめようと考えています。スペースを見てください:)


今、あなたの質問への回答に関して、私はこれに行きます:

/api/formgroups/1
/api/formgroups/1/forms/123

リンクの維持とルートの設定は、今のところ多かれ少なかれその場しのぎです。

于 2013-02-06T22:31:08.720 に答える