POST和PUT的不同型号要求

假设我有一个控制器CatController其中包含GET,POST和PUT操作。 它们都使用相同的Cat资源,如下所示:

 public class CatDto { public int Id { get; set; } [Required] public string Name { get; set; } [Required] public bool IsFriendly {get; set; } } 

但是,只有在创建新cat(POST)时才需要NameIsFriendly属性,但在更新它(PUT)时可选,以允许仅更新单个属性。

到目前为止,我处理这个问题的方法只是有两个类,一个CreateCatUpdateCat ,它们具有相同的属性但不同的数据注释。 但是我不想要维护两个几乎相同的类。

我当然可以在每个操作中手动validation模型,但数据注释对于诸如全局模型validation器和自动生成Swagger架构之类的东西非常有用。

我也使用Swagger模式自动生成SDK(使用ApiMatic ),这导致生成两个重复的类( CreateCatUpdateCat ),实际上应该只是单个资源( Cat )。

有没有另一种方法可以实现我只想用一个class级做的事情?

我更愿意保持单独的模型。 你可以有一个带有所有常见属性的基本抽象(或不是)模型,虽然这不是必需的,只需添加第三个类。 有必要吗? 我会说不。

POST和PUT之间存在细微差别。如果您已经在PUT端点中拥有Id属性,则POST和PUT都不需要Id属性。 这使得无需检查URL中的Id是否与模型中的Id匹配。

您的示例不会显示差异,但在许多情况下,您确实不想更新某些字段。 例如,假设您有一个Created和Updated日期字段,您不希望通过PUT更改您创建的日期。 您不希望通过PUT更新的数据越多,模型之间的差异就越明显和有价值。

在您的情况下,即使使用这两个属性,我仍然会创建2个不同的模型,即使它们几乎相同,这也会对API的工作方式产生期望,并在其他所有人的脑海中创建一个清晰的设计。

我建议不要考虑你要求的设计。 根据RFC [RFC7231],您可以在此处找到建议不要在PUT方法中进行部分内容更新。

“允许PUT在给定目标资源上的原始服务器必须向包含Content-Range头字段的PUT请求发送400(错误请求)响应([RFC7233]的第4.2节),因为有效载荷可能是部分的错误地将PUT作为完整表示的内容。通过将具有与较大资源的一部分重叠的状态的单独标识的资源作为目标,或者通过使用为部分更新专门定义的不同方法(例如,部分内容更新)是可能的。 ,[RFC5789]中定义的PATCH方法。“

优先解决方案是使用PATCH方法而不是PUT。 补丁方法在此链接的RFC中描述。 引入PATCH方法用于部分资源修改

因此,查找PATCH方法或者如果您想使用PUT,可能有一个单独的端点,只接受两个值中的一个。

有关PATCH方法的更多信息,请参见此处

因此,要么使用PATCH方法,要么使用PUT创建不同的模型和终点以满足部分更新。