ServiceStack - 使用多个密钥定义资源的路由

时间:2017-01-03 21:33:13

标签: c# servicestack

在处理ServiceStack中具有多个密钥的资源时,哪个选项最适合定义路由?

对于某些情况,我需要获得给定客户的所有交易。可以通过ID号或卡号识别唯一的客户。我创建了一个请求DTO如下......

public class GetCustomerTransactions : IReturn<List<Transactions>>
{
    public int? CustomerId { get; set; }
    public long? CardNumber { get; set; }
}

该路线目前定义为......

[Route("/customers{" + nameof(CustomerId) + "}/transactions", "GET")]

理想情况下,我希望这样的事情......

[Route("/customers{" + nameof(CustomerId) + "}/transactions", "GET")]
[Route("/customers{" + nameof(CardNumber) + "}/transactions", "GET")]

目前我有三种选择。

选项1 创建两个路由如下。第一条路线将允许使用客户ID找到交易。第二条路线允许使用客户ID或卡号找到交易。这里的问题是,如果两个代码恰好与同一个人不对应,有人可能会填充这两个值并可能返回错误信息。

[Route("/customers{" + nameof(CustomerId) + "}/transactions", "GET")]
[Route("/customers/transactions", "GET")]

选项2 强制客户端使用不同的端点查找客户,并将客户ID作为响应的一部分返回。然后仅使用客户ID定义路线,并从请求DTO中删除卡号。

选项3 将请求DTO更改为具有一个名为&#34; CustomerIdOrCardNumber&#34;的字段。然后实现逻辑以确定传入的值是客户ID还是卡号

我也对其他选项持开放态度。不确定这种情况的最佳方法。

2 个答案:

答案 0 :(得分:2)

我不会为每个客户资源维护多条路由,因为它会不必要地使您的API复杂化并使每条服务的路由倍增。

我只维护您希望维护语义URL结构的客户资源的客户ID,例如:

[Route("/customers/{" +  nameof(Id) + "}")]
public class GetCustomer : IReturn<Customer>
{
    public int Id { get; set; }
}

[Route("/customers/{" +  nameof(Id) + "}/transactions")]
public class GetCustomerTransactions : IReturn<List<Transactions>>
{
    public int Id { get; set; }
}

然后我只有一个“发现”服务,您可以使用不同的属性解析Customer,例如:

[Route("/customers")]
public class GetCustomers : IReturn<List<Customer>>
{
    public int[] CustomerIds { get; set; }
    public long[] CardNumbers { get; set; }
    public string[] Emails { get; set; }
}

虽然我倾向于使用AutoQuery,因为它大大减少了创建此类搜索服务的工作量,例如:

[Route("/customers/search")]
public class SearchCustomers : QueryDb<Customer>
{
    public int[] CustomerIds { get; set; }
    public long[] CardNumbers { get; set; }
    public string[] Emails { get; set; }
}

答案 1 :(得分:1)

您正在执行不同的操作,因此我认为您应该有两条路线,特别是因为int可以转换为long,因此可能会发生一些冲突。

类似的东西:

[Route("/customers/ById/{" + nameof(CustomerId) + "}/transactions", "GET")]
[Route("/customers/ByCardNumber/{" + nameof(CardNumber) + "}/transactions", "GET")]

或者:

[Route("/customers{" + nameof(CustomerId) + "}/transactionsByCId", "GET")]
[Route("/customers{" + nameof(CardNumber) + "}/transactionsByCN", "GET")]

我赞成第一个,但你明白了。