web-dev-qa-db-ja.com

ASP.NET Web API-1つのコントローラーでの複数のGETアクション

Usersコントローラーがあり、基本的なRESTパターンは正常に機能しています。ただし、そのユーザーのすべてのユーザーグループを返す追加のパターンusers/{id}/usergroupsが必要です。

さらに多くのコントローラで同様のルートが必要になると想像するので、これを実装する最良の方法は何でしょうか。デフォルトのものだけでは十分ではありません...

エラー

リクエストに一致する複数のアクションが見つかりました:タイプApi.Controllers.UsersController System.Collections.Generic.IEnumerable`1 [Api.Models.Users.UserGroup] GetUserGroups(Int32)onのApi.Models.Users.User GetUser(Int32)タイプApi.Controllers.UsersController

コード

// GET api/Users
public IEnumerable<User> GetUsers()

// GET api/Users/5
public User GetUser(int id) // THIS IS CONFLICT 1

// PUT api/Users/5
public HttpResponseMessage PutUser(int id, User user)

// POST api/Users
public HttpResponseMessage PostUser(User user)

// DELETE api/Users/5
public HttpResponseMessage DeleteUser(int id)

// GET api/Users/5/UserGroups
public IEnumerable<UserGroup> GetUserGroups(int id)  // THIS IS CONFLICT 2

編集1

私はamhedの提案を実行しましたが、問題は解決しません。

// GET api/Users/5
[HttpGet, ActionName("getuser")]
public User GetUser(int id) // THIS STILL DOES NOT WORK

// GET api/Users/5/UserGroups
[HttpGet, ActionName("usergroups")]
public IEnumerable<UserGroup> GetUserGroups(int id) // THIS WORKS

// ROUTES
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "{controller}/{id}/{action}",
    defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional }
);
19
Stan

次のいずれかを実行できます。1つのGetメソッドを定義し、オプションのIdパラメータを次のように指定します。

public IEnumerable<User> GetUsers(int? id){
    if (id.HasValue)
    {
         //return collection of one item here
    }
    //return collection of all items here
}

または、ActionName属性で装飾された複数のGetを持つことができます

// GET api/Users
[ActionName("GetAll")]
public IEnumerable<User> GetUsers()

// GET api/Users/5
[ActionName("Get")]
public User GetUser(int id) // THIS IS NO LONGER IN CONFLICT

次に、RouteConfigで次のようにルートを定義します。

routes.MapHttpRoute(
            name: "DefaultApiWithAction",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );
19
amhed

私はWeb API v1を使用して立ち往生しており、これに対する次の解決策を考え出しました。すべての一般的なルートについて、ActionNameを「デフォルト」として宣言します。次に、ルート構成で、デフォルトのaction = "Default"を設定します。これにより、/ Users/5への呼び出しがusers/5/defaultに変更され、適切な場所にマッピングされます。この解決策で私が見つけた唯一の問題は、ドキュメントにルートの/ Default部分が表示されることです。この男のようにビューを編集してこれらを除外できるようです( https://stackoverflow.com/a/29353198/4374666 )。

V2を使用している場合は、属性ルーティングが最もクリーンな方法のようです。

// GET api/Users/5
[HttpGet, ActionName("Default")]
public User GetUser(int id) // THIS STILL DOES NOT WORK

// GET api/Users/5/UserGroups
[HttpGet, ActionName("usergroups")]
public IEnumerable<UserGroup> GetUserGroups(int id) // THIS WORKS

// ROUTES
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}/{action}",
    defaults: new { id = RouteParameter.Optional,
 action = "Default" }
);
1
Vince Cipriani