ASP.NET WebApi – 一个控制器中的多个GET操作

我有Users控制器和基本的REST模式工作正常。 但是,我需要一个额外的模式users/{id}/usergroups ,它将返回该用户的所有用户组。

实现这一目标的最佳方法是什么,因为我想我将需要更多控制器上的类似路由。 只是默认的还不够……

错误

找到了与请求匹配的多个操作:Api.Models.Users.User GetUser(Int32)类型Api.Controllers.UsersController System.Collections.Generic.IEnumerable`1 [Api.Models.Users.UserGroup] GetUserGroups(Int32)on键入Api.Controllers.UsersController

 // GET api/Users public IEnumerable 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 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 GetUserGroups(int id) // THIS WORKS // ROUTES config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "{controller}/{id}/{action}", defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional } ); 

你可以:只需定义一个Get方法,并有一个可选的Id参数,如下所示:

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

或者您可以使用ActionName属性装饰多个Gets

 // GET api/Users [ActionName("GetAll")] public IEnumerable 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 } ); 

我坚持使用Web API v1,并提出了以下解决方案。 对于所有常规路由,将ActionName声明为“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 GetUserGroups(int id) // THIS WORKS // ROUTES config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "{controller}/{id}/{action}", defaults: new { id = RouteParameter.Optional, action = "Default" } );