简体   繁体   English

在对我的API进行版本控制时,如果使用相同的DTO,如何维护swagger文档?

[英]When versioning my API, how do I maintain swagger documentation if I use the same DTO?

It has been recommended to favor defensively evolving a DTO over time when versioning endpoints, but I'm finding it difficult to do without losing what I consider some key beneficial functionality provided by ServiceStack. 在版本化端点时,建议在一段时间内支持防御性地发展DTO ,但我发现很难在不失去我认为ServiceStack提供的一些关键有益功能的情况下做到这一点。

I am currently using ServiceStack v3, but can upgrade to v4 if/when necessary. 我目前正在使用ServiceStack v3,但如果/必要时可以升级到v4。

When implementing my Service, I can specify multiple implementations of Get() with different contracts, and ServiceStack maps the data coming in accordingly. 在实现我的服务时,我可以使用不同的协定指定Get()的多个实现,并且ServiceStack相应地映射进入的数据。

Works: 作品:

public object Get(EntityBrowse) { ... } // returns multiple of a single entity
public object Get(Entity) { ... } // returns a single entity

Also Works: 还有效:

public object Get(Contracts.v1.Entity) { ... } 
public object Get(Contracts.v2.Entity) { ... }

Does not work: 不起作用:

public object Post(Contracts.v1.Entity) { ... }
public object Post(Contracts.v2.Entity) { ... }

This case doesn't work to the point where all POSTs that come through this service are mapping to the v1 contract, even though the fields don't match. 这种情况不起作用,通过此服务的所有POST都映射到v1合同,即使字段不匹配。 Even the swagger docs are showing the wrong v1 properties, but the correct summary/notes from the v2 DTO. 即使是昂首阔步的文档也显示错误的v1属性,但是来自v2 DTO的正确摘要/注释。

I would like to have a separate DTO for each major version of a given endpoint for a few reasons: 我想为给定端点的每个主要版本提供单独的DTO,原因如下:

  1. Swagger . 摇摇晃晃 Swagger docs generated from DTOs with a lot of fields can be confusing to the end users of public APIs. 从具有大量字段的DTO生成的Swagger文档可能会使公共API的最终用户感到困惑。 How does the user know which fields are for the version of the endpoint they want to use? 用户如何知道哪些字段适用于他们想要使用的端点版本? I could document this per field, but I think it is easier to show the end user only the fields they care about at the time. 我可以在每个字段中记录这个,但我认为向最终用户显示他们当时关心的字段更容易。 Different customers will use v2 without ever knowing v1 existed. 不同的客户将使用v2而不知道v1存在。

  2. Validation . 验证 ServiceStack provides validators per Type. ServiceStack为每个Type提供验证器。 This is perfect, except that if my DTO's required fields may drift over time, I can't continue using the same validator without some special casing. 这是完美的,除非我的DTO所需的字段可能会随着时间的推移而漂移,我不能在没有特殊外壳的情况下继续使用相同的验证器。 Maybe this is an acceptable loss? 也许这是一个可以接受的损失?

  3. Deprecation . 弃用 After a given time, v1 will be deprecated. 在给定时间之后,v1将被弃用。 v1 represents the legacy implementation of the endpoint, before there was versioning, and before there were consistent contracts between entities (eg, using "Name" vs "Title", "TypeId" vs "Type"). v1表示端点的遗留实现,在版本控制之前,以及实体之间存在一致的合同之前(例如,使用“Name”与“Title”,“TypeId”vs“Type”)。 Evolving a DTO over time after this seems more reasonable, but while v1 exists, the endpoints are restricted by the decisions developers made possibly up to a decade ago. 在此之后随着时间的推移演变DTO似乎更合理,但是当v1存在时,端点受到开发人员可能在十年前做出的决策的限制。

After reading over this a few times, I'm thinking that maybe I should be creating separate services to support older functionality. 在阅读了几次之后,我想也许我应该创建单独的服务来支持旧功能。

The key differences between versions of my endpoints are: 我的端点版本之间的主要区别是:

  • permissions 权限
  • field names 字段名称
  • organization and mapping of fields (eg, removal of nested objects) 组织和字段映射(例如,删除嵌套对象)
  • implementation details (eg, how many results are returned by default) 实现细节(例如,默认返回多少结果)

Should I consider breaking my versions out in to separate services? 我应该考虑将我的版本分解为单独的服务吗? Should I load up a single DTO with all the fields and just outline the supported version per property? 我是否应该在所有字段中加载单个DTO,并仅列出每个属性支持的版本?

I'd strongly recommend against using multiple versions of the same Request DTO in the same Service, you should instead version your DTO's defensively so your Request DTO can support multiple versions. 我强烈建议不要在同一个服务中使用同一个Request DTO的多个版本,你应该防御版DTO,这样你的Request DTO就可以支持多个版本了。 It's especially bad trying to maintain multiple versions of the same Service in a statically typed language which causes a lot of friction, duplicated code, maintenance, etc. 尝试使用静态类型语言维护同一服务的多个版本会导致大量摩擦,重复代码,维护等,这一点尤其糟糕。

If you must maintain different versions, I'd recommend maintaining and hosting different branches and have a reverse proxy to redirect /v1/ and /v2/ API requests to old and new ServiceStack instances. 如果您必须维护不同的版本,我建议维护和托管不同的分支,并使用反向代理将/v1//v2/ API请求重定向到新旧ServiceStack实例。 That way once all customers have migrated off v1 you can drop it and your v2 will be clean without legacy v1 cruft infecting the current code base. 这样一旦所有客户都从v1迁移出来,你可以放弃它,你的v2将是干净的,没有传统的v1 cruft感染当前的代码库。 But my recommendation is to version the same Request DTO defensively so you don't have to maintain multiple versions, ServiceStack's message-based design makes this a lot easier. 但我的建议是在防御上对相同的Request DTO进行版本控制,这样您就不必维护多个版本,ServiceStack基于消息的设计使这更容易。 It will also reduce confusion both inside and out, trying to maintain multiple versions is confusing for Developers maintaining the Service and anyone consuming them. 它还可以减少内部和外部的混淆,尝试维护多个版本会让维护服务的开发人员和任何使用它的人感到困惑。

In ServiceStack each Request DTO Type should be unique and only have a single implementation, however most metadata services require the Request DTO name to be unique as well and many of the languages in Add ServiceStack Reference also requires all DTO's to be unique which is our recommendation. 在ServiceStack中,每个请求DTO类型应该是唯一的,并且只有一个实现,但是大多数元数据服务要求Request DTO名称也是唯一的,并且Add ServiceStack Reference中的许多语言也要求所有DTO都是唯一的,这是我们的建议。 If you absolutely must have different types with different versions append the version on the Request DTO, eg GetEntitiesV1 and GetEntitiesV2 - these names will be hidden from users using your published Custom Routes. 如果您必须使用不同版本的不同类型在Request DTO上附加版本,例如GetEntitiesV1GetEntitiesV2 - 这些名称将使用您发布的自定义路径向用户隐藏。

ServiceStack's Swagger Support has seen a lot of updates in v4, if you see issues in v3, you can use the Free Quotas in v4 to see if the issues have been resolved. ServiceStack的Swagger支持已经在v4中看到了很多更新,如果你在v3中看到问题,你可以使用v4中免费配额来查看问题是否已经解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 Swashbuckle 在 Swagger API 文档/OpenAPI 规范中包含子类? - How do I include subclasses in Swagger API documentation/ OpenAPI specification using Swashbuckle? 映射器的结果为 NULL? 如何将我的 api 请求映射到 dto? - Result of mapper is NULL? How do I map my api request to a dto? 如何替换我的视图 model 并使用 DTO 返回视图? - How do I replace my view model and use DTO to return to the view? 如何为 SignalR 生成 API 文档 - How do I generate API documentation for SignalR 我如何使用这个特定的映射器映射我的模型和 dto? - How do i map my model and dto using this particular mapper? 如何将实体框架与 RootObject DTO 一起使用? - How do I use Entity Framework with a RootObject DTO? 如何保持第三方API和我自己的数据库之间的一致性? - How do I maintain consistency between third-party API and my own database? 我是否需要使用DTO或POCO - Do I need to use DTO or POCO 如何将Swagger与来自Web API操作方法的动态参数一起使用? - How do I use Swagger with dynamic parameters from a Web API Action Method? linq2sql:使用ExceuteQuery <dto> 当返回的行不在我的dto中? 我可以使用通用数据类型吗? - linq2sql: using ExceuteQuery<dto> when rows returned are not in my dto? Can i use a generic data type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM