我的建议是您没有正确使用 REST。有a good answer about how to best structure a ServiceStack REST service。刚开始的时候很常见,我也遇到过这样的问题。
了解您的用例:
在您的具体情况下,如果我们查看 /orders/customers/7 这会更好,您是否这样想:
/customers/7/订单
你这样做的原因:
- 它解决了您的路线模糊问题
- 上下文很清楚。我们可以看到我们正在与 客户 7 合作,而无需导航很长的 url
- 我们可以看到“与客户 7”我们想要他们的订单
考虑这样的路由:
/orders Everybody's Orders
/orders/1 Order 1 (without being aware of the customer it belongs to)
/customers All Customers
/customers/7 Customer 7's details
/customers/7/orders All Customer 7's orders
/customers/7/orders/3 Customer 7's order number 3
这样做的好处是对数据的操作是一致的。所以你想找到所有取消的订单:
/orders/cancelled
您想通过orderId取消特定订单
/orders/4/cancel
您想列出特定客户的未结订单
/customers/6/orders/open
您想列出客户 6 的已取消订单
/customers/6/orders/cancelled
您想取消正在查看的客户 6 的订单
/customers/6/orders/2/cancel
显然这些只是场景,您的路线会有所不同。
简化动作处理程序:
您可能希望定义您的操作处理程序,以便它们可以应对来自多个路线的情况。我的意思是,一个操作处理程序将负责列出订单
/orders
/customers/6/orders
我要做的是:
[Route("/orders","GET")]
[Route("/customers/{CustomerId}/orders","GET")]
public class ListOrdersRequest : IReturn<List<Order>>
{
public int? CustomerId { get; set; }
}
所以你可以看到两个订单列表路由进来。如果他们使用/orders,那么我们的customerId 将没有值,但其他路由会有值。所以在我们的动作处理程序中,我们可以简单地测试一下:
public List<Order> Get(ListOrdersRequest request)
{
// Use `CustomerId` to narrow down your search scope
if(request.CustomerId.HasValue){
// Find customer specific orders
} else {
// Find all orders
}
return orders;
}
客户端问题:
因此,为了解决您使用“类型化”客户端的问题。使用上述方法创建路由和操作处理程序将允许您执行以下操作:
client.Get(new ListOrdersRequest { CustomerId = 7 }); // To get customer 7's orders
client.Get(new ListOrdersRequest()); // All orders
因此为您提供了一种清晰的列出订单的方法。
最后的想法:
显然,这意味着您将不得不重做现有的工作,这可能会很痛苦,但这是最好的方法,值得付出努力。
我希望这可以帮助您了解最佳结构。
更新:
@stefan2410 要求我解决 Kyle 在 GET 请求的路由中使用 int[] 的问题:
如果您想在 GET 请求中使用 int[],您必须考虑在 URL 传输期间更改它,以便可以 RESTful 方式使用它。
所以你可以这样做:
class OrdersRequest
{
public string Ids { get; set; }
public OrdersRequest(int[] ids)
{
Ids = string.Join(",", Array.ConvertAll(ints, item => item.ToString()));
}
}
client.Get(new OrdersRequest(new [] {1,2,3}));
创建路由/orders/1,2,3 并匹配/orders/{Ids}。这样做的问题是为了在服务器端使用 Id,您必须将字符串 "1,2,3" 转换回 int[]。
处理请求中int[] 的更好方法是使用 POST。所以你可以这样做:
class OrdersRequest
{
public int[] Ids { get; set; }
public OrdersRequest(int[] ids)
{
Ids = ids;
}
}
client.Post(new OrdersRequest(new[] {1,2,3}));
创建路由/orders并匹配路由/orders。