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

时间:2022-11-05 11:12:10

I have Users controller and basic REST pattern is working just fine. However I need one additional pattern users/{id}/usergroups that will return all user groups for that user.

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

What would be the best way to implement this since I imagine I will need similar routes on many more controllers. Just default ones are not enough...

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

Error

Multiple actions were found that match the request: Api.Models.Users.User GetUser(Int32) on type Api.Controllers.UsersController System.Collections.Generic.IEnumerable`1[Api.Models.Users.UserGroup] GetUserGroups(Int32) on type Api.Controllers.UsersController

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

Code

// 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

Edit 1

I did what amhed suggested and it doesn't solve the issue.

我做了建议的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 }
);

2 个解决方案

#1


19  

You can either: just define one Get method, and have an optional Id Parameter like this:

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

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

Or you can have multiple Gets decorated with the ActionName Attribute

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

// 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

And then define the routes on your RouteConfig like so:

然后在RouteConfig上定义路由,如下所示:

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

#2


1  

I'm stuck using Web API v1 and came up w/ the following solution to this. For all of your general routes, declare the ActionName as "Default". Then in your route config, set the default action="Default". This changes your call to /Users/5 to users/5/default and ensures it maps to the right place. The only problem I've found w/ this solution is that the documentation will show the /Default part of the route. It looks like you can edit your view to exclude these as this guy did (https://*.com/a/29353198/4374666).

我坚持使用Web API v1,并提出了以下解决方案。对于所有常规路由,将ActionName声明为“Default”。然后在路由配置中,设置默认操作=“默认”。这会将您对/ Users / 5的调用更改为users / 5 / default,并确保将其映射到正确的位置。我发现这个解决方案的唯一问题是文档将显示路径的/ Default部分。看起来您可以编辑视图以排除这些人(https://*.com/a/29353198/4374666)。

If you're using v2, it seems like Attribute Routing would be the cleanest way.

如果您使用的是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


19  

You can either: just define one Get method, and have an optional Id Parameter like this:

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

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

Or you can have multiple Gets decorated with the ActionName Attribute

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

// 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

And then define the routes on your RouteConfig like so:

然后在RouteConfig上定义路由,如下所示:

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

#2


1  

I'm stuck using Web API v1 and came up w/ the following solution to this. For all of your general routes, declare the ActionName as "Default". Then in your route config, set the default action="Default". This changes your call to /Users/5 to users/5/default and ensures it maps to the right place. The only problem I've found w/ this solution is that the documentation will show the /Default part of the route. It looks like you can edit your view to exclude these as this guy did (https://*.com/a/29353198/4374666).

我坚持使用Web API v1,并提出了以下解决方案。对于所有常规路由,将ActionName声明为“Default”。然后在路由配置中,设置默认操作=“默认”。这会将您对/ Users / 5的调用更改为users / 5 / default,并确保将其映射到正确的位置。我发现这个解决方案的唯一问题是文档将显示路径的/ Default部分。看起来您可以编辑视图以排除这些人(https://*.com/a/29353198/4374666)。

If you're using v2, it seems like Attribute Routing would be the cleanest way.

如果您使用的是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" }
);