建议在版本化端点时支持defensively evolving a DTO over time,但我发现很难做到不丢失我认为ServiceStack提供的一些关键有用功能。
我目前正在使用ServiceStack v3,但如果/在必要时可以升级到v4。
实现我的服务时,我可以使用不同的契约指定Get()的多个实现,ServiceStack会相应地映射相应的数据。
使用:
public object Get(EntityBrowse) { ... } // returns multiple of a single entity
public object Get(Entity) { ... } // returns a single entity
也有效:
public object Get(Contracts.v1.Entity) { ... }
public object Get(Contracts.v2.Entity) { ... }
不起作用:
public object Post(Contracts.v1.Entity) { ... }
public object Post(Contracts.v2.Entity) { ... }
这种情况并不适用于通过此服务发送的所有POST都映射到v1合同的地方,即使这些字段不匹配。即使是昂首阔步的文档也显示错误的v1属性,但是来自v2 DTO的正确摘要/注释。
我希望为给定端点的每个主要版本提供单独的DTO,原因如下:
扬鞭即可。从具有大量字段的DTO生成的Swagger文档可能会使公共API的最终用户感到困惑。用户如何知道哪些字段适用于他们想要使用的端点版本?我可以在每个字段中记录这个,但我认为向最终用户显示他们当时关心的字段更容易。不同的客户将使用v2而不知道存在v1。
验证即可。 ServiceStack为每个Type提供验证器。这是完美的,除非我的DTO所需的字段可能会随着时间的推移而漂移,我无法在没有特殊外壳的情况下继续使用相同的验证器。也许这是可以接受的损失?
弃用即可。在给定时间之后,v1将被弃用。 v1代表端点的遗留实现,在版本化之前,以及实体之间存在一致的合同之前(例如,使用"名称" vs"标题"," TypeId&# 34; vs" Type")。在此之后随着时间的推移演变DTO似乎更合理,但是当v1存在时,端点受到开发人员可能在十年前做出的决策的限制。
在阅读了几次之后,我想我可能应该创建单独的服务来支持旧功能。
我的端点版本之间的主要区别是:
我是否应该考虑将我的版本分解为单独的服务?我是否应该在所有字段中加载单个DTO,并概述每个属性支持的版本?
答案 0 :(得分:3)
我强烈建议您不要在同一个服务中使用同一个请求DTO的多个版本,而应该version your DTO's defensively,以便您的请求DTO可以支持多个版本。尝试使用静态类型语言维护同一服务的多个版本会导致大量摩擦,重复代码,维护等,这一点特别糟糕。
如果您必须维护不同的版本,我建议维护和托管不同的分支,并建议使用反向代理将/v1/
和/v2/
API请求重定向到旧的和新的ServiceStack实例。这样一旦所有客户都从v1迁移出来,你可以放弃它,你的v2将是干净的,没有传统的v1 cruft感染当前的代码库。但我的建议是在防御上对相同的Request DTO进行版本控制,这样您就不必维护多个版本,ServiceStack的基于消息的设计使这更容易。它还可以减少内部和外部的混淆,尝试维护多个版本会让维护服务的开发人员和任何使用它的人感到困惑。
在ServiceStack中,每个请求DTO类型应该是唯一的,并且只有一个实现,但是大多数元数据服务要求请求DTO名称也是唯一的,Add ServiceStack Reference中的许多语言也需要所有DTO&#39 ; s是唯一的,这是我们的建议。如果您必须使用不同版本的不同类型,请在申请DTO上附加该版本,例如: GetEntitiesV1
和GetEntitiesV2
- 这些名称将使用您发布的自定义路由向用户隐藏。
ServiceStack's Swagger Support在v4中看到了很多更新,如果您在v3中看到问题,可以使用Free Quotas in v4查看问题是否已得到解决。