ASP.NET Web API路由设计(多个路由)

3

我目前正在使用ASP.NET Web API设计一个REST api。

我希望提供以下方法(http方法无关 - 应适用于所有):

  • /api/client
  • /api/client/CID1234(CID1234 = Id)
  • /api/client/CID1234/orders(orders = action)

问题是: Id应该是可选的 - /api/client可能返回客户列表 Action也应该是可选的 - 在一种情况下,我想获取特定的客户,在另一种情况下,我想对该客户执行某个操作(RPC风格)

我认为我不能使用约束,因为我使用的“IDs”看起来非常不同。

这种方法行不通:

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

这种方法也没有起作用:
config.Routes.MapHttpRoute(
            name: "RpcStyleApi",
            routeTemplate: "rest/{controller}/{action}"
        );

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

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

例如,由于不能区分“action”和“id”,因此此代码返回404: “在名称为‘CID1234’的控制器上找不到与之匹配的‘动作’。” 我应该选择自定义Actionselector来获得所需的灵活性吗?还是可以使用Web API内置功能来实现?我知道有些人可能希望将订单作为单独的实体。但我也可以在那里使用真正的“actions”(而不是“entities”),例如“lostpassword”、“changepassword”等等。 谢谢您的建议。 附言:像这里描述的东西并不是我愿意做的事情。糟糕的API设计。

当你说你的ID看起来非常不同时,你是什么意思?它们是否像你的示例一样以CID为前缀?- 马克·琼斯 刚刚编辑 - Mark Jones
它们都遵循一种模式。但通常每个实体都有其自己独特的模式。有时需要支持旧模式和新模式。例如,有4种不同类型的产品“ID”... - lapsus
3个回答

1
这实际上是构建RESTful API的最佳实践之一,以下是一个小视频,介绍了在构建API时需要考虑的不同方面https://www.youtube.com/watch?v=ZpqCN8iO9Y8解决方案:您不需要更改映射路由,您只需要在每个方法的顶部使用方法属性,如下所示。
\\ api/clients [this should be clients not client if its returning a list]
[Route("api/clients")]
public IHttpActionResult Get()
{
   return Ok("here you list of clients");
}

/api/client/CID1234 (CID1234 = Id)
[Route("api/clients/{Id}")]
public IHttpActionResult Get(string Id)
{
   return Ok("use the Id to retrieve the client details");
}

/api/client/CID1234/orders (orders = action)
[Route("api/clients/{Id}/orders")]
public IHttpActionResult GetOrders(string Id)
{
   return Ok("use the Id to retrieve the client orders");
}

关于可选项,现在你可以在方法中构建自己的逻辑来获取其值。
本文具有更多关于此点的详细信息。

https://aspnetwebstack.codeplex.com/wikipage?title=Attribute%20Routing%20in%20MVC%20and%20Web%20API

PS: 这是使用 .Net Framework 4.5.2 和 Owin。


0

不太确定为什么你的第二种方法不起作用,但以下路由配置对我有效

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

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

0
如果您按照以下方式定义路由:
config.Routes.MapHttpRoute(
    name: "RpcStyleApi1",
    routeTemplate: "rest/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional, action = "Get" }
);

config.Routes.MapHttpRoute(
    name: "RpcStyleApi2",
    routeTemplate: "rest/{controller}/{id}/{action}"
);

然后,您可以在控制器上创建如下的方法:

public string Get()
{
    return "GET";
}

public string Get(string id)
{
    return "GETID";
}

public string Orders(string id)
{
    return "GETORDERS";
}

这应该可以处理您的URL组合

  • /rest/client
  • /rest/client/CID1234
  • /rest/client/CID1234/orders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接