在处理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还是卡号
我也对其他选项持开放态度。不确定这种情况的最佳方法。
答案 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")]
我赞成第一个,但你明白了。