【问题标题】:How to map different actions to Web API methods that would have same signature如何将不同的操作映射到具有相同签名的 Web API 方法
【发布时间】:2024-05-19 21:40:02
【问题描述】:

我正在尝试使用 Web Api 最佳实践创建 REST 服务,但遇到了一种我不知道如何处理的情况。

假设我有组,并且在每个组内我都有用户。

这就是我的 GroupController 的样子:

[RoutePrefix("api/v1/groups")]
public class GroupsController : ApiController
{
    [HttpGet]
    [Route("{id:int}")]
    public IHttpActionResult Get(int id)
    {
        return Ok();
    }

    // I also want to add endpoint which fetches all the users inside of group and I'd like to do it like this:
    [HttpGet]
    [Route("{id:int}/users")]
    public IHttpActionResult Get(int id)
    {
        return Ok();
    }
}

如您所见,我的第二个方法无法编译,因为我们不能在同一个类中有两个具有相同签名的方法。

我的路线模板看起来像标准的:

config.Routes.MapHttpRoute(
               name: "DefaultRouting",
               routeTemplate: "api/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional }
           ); 

我知道我可以添加一个映射动作方法名称的路由,但我想知道是否有更好的方法来实现我的目标。我想坚持编写 RESTful 服务的最佳原则。据我所知,其中一个建议是避免自定义操作名称,因为这对于 WCF 服务更为常见。

【问题讨论】:

    标签: rest asp.net-web-api asp.net-mvc-routing


    【解决方案1】:

    不要混用MapHttpRoute() 风格的路由配置和基于属性的路由。使用其中一个更简单(我更喜欢基于属性,因为它是显式的并且允许更清晰的类方法名称)。

    您似乎也没有调用在您的配置上启用基于属性的路由所需的方法 - config.MapHttpAttributeRoutes()

    最后,我将您的方法重命名如下,以确保方法签名中没有冲突:GetGroups(int id)GetUsersForGroup(int id)

    【讨论】:

    • 那么,我可以通过导航到 api/v1/groups/1/usersforgroup 来点击“GetUsersForGroup(int id)”吗?
    • 不,您的属性的路径为api/v1/groups/1/users。这也是我更喜欢属性路由的原因,因为路由不依赖于方法名。
    • 我的意思是它会点击“GetUsers(int id)”方法,它确实会。这就是我将您的回复标记为答案的原因。
    • 我猜这是因为 URL 匹配控制器上的路由之一,即使在这种情况下它是部分匹配。
    • 据我所知,如果您使用自定义操作名称调用“GET”端点,它会映射“Get”之后的短语,在我的情况下它会映射用户。