4

私は Web API を使用して REST サービスを作成しました。Brian Mulloy によるこのWeb API 設計のセクションを読んだ後、Web API との関連付けを実装する方法を見つけようとしていました。

Web API 設計の抜粋:

協会

リソースは、ほとんどの場合、他のリソースとの関係を持っています。これらの関係を WebAPI で表現する簡単な方法は何ですか?

名詞でモデル化した API をもう一度見てみましょう。動詞は良くなく、dogs リソースと対話する API です。/dogs と dogs/1234 の 2 つのベース URL があったことを思い出してください。

リソースとコレクションを操作するために HTTP 動詞を使用しています。私たちの犬は飼い主のものです。特定の所有者に属するすべての犬を取得するか、その所有者の新しい犬を作成するには、GET または POST を実行します。

GET /owners/5678/dogs
POST /owners/5678/dogs

現在、関係は複雑になる可能性があります。飼い主は獣医師と関係があり、犬と関係があり、食べ物と関係があります。これらをつなぎ合わせて 5 ~ 6 レベルの深さの URL を作成する人を目にすることは珍しくありません。1 つのレベルの主キーを取得したら、特定のオブジェクトを既に取得しているため、通常は上記のレベルを含める必要はありません。言い換えれば、URL が /resource/identifier/resource の上にあるものよりも深い場合はあまり必要ないはずです。

そこで、次のような関連付けのコントローラーメソッドを追加しようとしました。

public class EventsController : ApiController
{
    // GET api/events
    public IEnumerable<Event> Get()
    {
        // get list code
    }

    // GET api/events/5
    public Event Get(int id)
    {
        // get code
    }

    // POST api/events
    public void Post([FromBody]Event evnt)
    {
        // add code
    }

    // POST api/events/5
    public void Post(int id, [FromBody]Event evnt)
    {
        // update code
    }

    // DELETE api/events/5
    public void Delete(int id)
    {
        // delete code
    }

    // GET api/events/5/guests
    public IEnumerable<Guest> Guests(int id)
    {
        // association code
    }
}

また、ルート テンプレートを次のように変更しました。

config.Routes.MapHttpRoute("ApiWithAssociations",
                           "api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
                           "api/{controller}/{id}",
                           new { id = RouteParameter.Optional });

残念ながら、イベント リソースの更新/投稿を行うと、HTTP 500 内部サーバー エラーが発生し、応答本文は次のようになります。

リクエストに一致する複数のアクションが見つかりました

System.Web.Http.HttpPostAttribute (およびその他の HTTP 動詞) の追加と組み合わせてルート テンプレートを変更しようとしましたが、役に立ちませんでした。

誰かがこれを試して、それを機能させましたか? どんな助けでも大歓迎です。http動詞の倍数を持つことが絶対に不可能な場合は、RESTサービスとの関連付けを放棄する必要があると思います.

編集:解決策

Radim Köhler の回答を使用して、これを機能させることができました。次のように、HttpGetAttribute を Guests メソッドに追加します。

// GET api/event/5/guests
[HttpGet]
public IEnumerable<Guest> Guests(int id)
{
    // association code
}

そして、次のようなデフォルトの GET アクションに対応する追加ルートを追加しました。

config.Routes.MapHttpRoute("DefaultGet",
                            "api/{controller}/{id}",
                            new {action = "Get"},
                            new {httpMethod = new HttpMethodConstraint(HttpMethod.Get)});
config.Routes.MapHttpRoute("ApiWithAssociations",
                            "api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
                            "api/{controller}/{id}",
                            new {id = RouteParameter.Optional});
4

1 に答える 1

2

解決策は、明示的な POST マッピングにある可能性があります

events/5 POST に使用される新しい定義を追加するだけです

// explicit Post() mapping 
config.Routes.MapHttpRoute(
    name: "DefaultPost",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "Post" }
    , constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
    );

// existing
config.Routes.MapHttpRoute("ApiWithAssociations",
    "api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
    "api/{controller}/{id}",
    new { id = RouteParameter.Optional });
于 2013-05-30T17:24:50.843 に答える