假设我有一个控制器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)时才需要Name
和IsFriendly
属性,但在更新它时(PUT)可选,以允许仅更新单个属性。
我迄今为止处理此问题的方法只是有两个类,CreateCat
和UpdateCat
,它们具有相同的属性但数据注释不同。但是,我不想要维持两个几乎完全相同的课程。
我当然可以在每个操作中手动验证模型,但数据注释对于全局模型验证器和自动生成Swagger模式等非常有用。
我还使用Swagger架构自动生成SDK(使用ApiMatic),这会导致生成两个重复的类(CreateCat
和{{1} })真正应该只是一个资源(UpdateCat
)。
是否有另一种方法可以实现我只尝试一个课程?
答案 0 :(得分:3)
我更喜欢保持单独的模型。 您可以使用具有所有常见属性的基本抽象(或不具有)模型,尽管这不是必需的,只需添加第三个类。有必要吗?我会说不。
POST和PUT之间存在细微差别。如果您已经在PUT端点中拥有Id属性,则POST和PUT都不需要Id属性。这样就无需检查URL中的Id是否与模型中的Id匹配。
您的示例不会显示差异,但在许多情况下,您确实不想更新某些字段。例如,假设您有一个Created和Updated日期字段,您不希望通过PUT更改您创建的日期。您不希望通过PUT更新的数据越多,模型之间的差异就越明显和有价值。
在您的情况下,即使使用这两个属性,我仍然会创建2个不同的模型,即使它们几乎相同,这也预示着API如何工作并在其他正在工作的人的脑海中创建一个清晰的设计在它上面。
答案 1 :(得分:1)
我建议不要考虑您要求的设计。根据RFC [RFC7231],您可以找到here,建议不要在PUT方法中进行部分内容更新。
“允许PUT在给定目标资源上的原始服务器必须发送 对包含a的PUT请求的400(错误请求)响应 Content-Range头字段([RFC7233]的第4.2节),因为 有效载荷可能是错误PUT的部分内容 作为一个完整的代表。可以通过以下方式更新部分内容 使用与a重叠的状态定位单独标识的资源 较大资源的一部分,或使用不同的方法 已经专门为部分更新定义(例如, [RFC5789]中定义的PATCH方法。“
优先解决方案是使用PATCH方法而不是PUT。补丁方法在此link中的RFC中进行了描述。引入PATCH方法用于部分资源修改
所以查找PATCH方法或者如果你想使用PUT,可能有一个单独的终点,只接受两个值中的一个。
可以找到有关PATCH方法的更多信息here
因此,要么使用PATCH方法,要么使用PUT创建不同的模型和终点以满足部分更新。