POST 和 PUT 的不同模型要求
Different model requirements for POST and 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; }
}
但是,Name
和 IsFriendly
属性应该只在创建新猫 (POST) 时是必需的,但在更新它 (PUT) 时是可选的,以允许只更新一个单身 属性.
到目前为止,我处理这个问题的方法只是简单地使用两个 class,一个 CreateCat
和 UpdateCat
,它们具有相同的属性但不同的数据注释。但是我不想维护两个几乎相同的 classes。
我当然可以在每个操作中手动验证模型,但数据注释对于全局模型验证器和自动生成 Swagger 模式等非常有用。
我还使用 Swagger 模式自动生成 SDK(使用 ApiMatic),结果生成了两个重复的 classes(CreateCat
和 UpdateCat
) 真正应该只是一个单一的资源 (Cat
).
是否有其他方法可以仅用一个 class 来实现我想做的事情?
老实说,我更喜欢保留不同的模型。
您可以拥有一个具有所有公共属性的基本抽象(或非)模型,尽管这不是必需的,只需添加第三个 class。有必要吗?我会说不。
POST 和 PUT.Neither POST 之间存在细微差别,如果您在 PUT 端点中已有 ID 属性,则 PUT 也不需要 ID 属性。这不需要检查 URL 中的 Id 是否与模型中的 Id 匹配。
您的示例并没有显示出差异,但在许多情况下,您确实不想更新某些字段。例如,假设您有创建日期和更新日期字段,您不想通过 PUT 更改您的创建日期。您不想通过 PUT 更新的数据越多,模型之间的差异就变得越明显和有价值。
在你的情况下,即使有这 2 个属性,我仍然会创建 2 个不同的模型,即使它们实际上是相同的,这设定了对 API 如何工作的期望,并在脑海中创建了一个清晰的设计其他正在为此工作的人。
我不推荐您要求的设计。根据 RFC [RFC7231],您可以找到 here 建议不要在 PUT 方法中更新部分内容。
"An origin server that allows PUT on a given target resource MUST send
a 400 (Bad Request) response to a PUT request that contains a
Content-Range header field (Section 4.2 of [RFC7233]), since the
payload is likely to be partial content that has been mistakenly PUT
as a full representation. Partial content updates are possible by
targeting a separately identified resource with state that overlaps a
portion of the larger resource, or by using a different method that
has been specifically defined for partial updates (for example, the
PATCH method defined in [RFC5789])."
首选解决方案是使用 PATCH 方法而不是 PUT。打补丁的方法在RFC中的thislink中有描述。部分资源修改引入了 PATCH 方法
所以查找 PATCH 方法,或者如果您想使用 PUT 可能有一个单独的端点,它只采用两个值之一。
可以找到有关 PATCH 方法的更多信息here
因此,要么采用 PATCH 方法,要么创建不同的模型和端点来满足使用 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; }
}
但是,Name
和 IsFriendly
属性应该只在创建新猫 (POST) 时是必需的,但在更新它 (PUT) 时是可选的,以允许只更新一个单身 属性.
到目前为止,我处理这个问题的方法只是简单地使用两个 class,一个 CreateCat
和 UpdateCat
,它们具有相同的属性但不同的数据注释。但是我不想维护两个几乎相同的 classes。
我当然可以在每个操作中手动验证模型,但数据注释对于全局模型验证器和自动生成 Swagger 模式等非常有用。
我还使用 Swagger 模式自动生成 SDK(使用 ApiMatic),结果生成了两个重复的 classes(CreateCat
和 UpdateCat
) 真正应该只是一个单一的资源 (Cat
).
是否有其他方法可以仅用一个 class 来实现我想做的事情?
老实说,我更喜欢保留不同的模型。 您可以拥有一个具有所有公共属性的基本抽象(或非)模型,尽管这不是必需的,只需添加第三个 class。有必要吗?我会说不。
POST 和 PUT.Neither POST 之间存在细微差别,如果您在 PUT 端点中已有 ID 属性,则 PUT 也不需要 ID 属性。这不需要检查 URL 中的 Id 是否与模型中的 Id 匹配。
您的示例并没有显示出差异,但在许多情况下,您确实不想更新某些字段。例如,假设您有创建日期和更新日期字段,您不想通过 PUT 更改您的创建日期。您不想通过 PUT 更新的数据越多,模型之间的差异就变得越明显和有价值。
在你的情况下,即使有这 2 个属性,我仍然会创建 2 个不同的模型,即使它们实际上是相同的,这设定了对 API 如何工作的期望,并在脑海中创建了一个清晰的设计其他正在为此工作的人。
我不推荐您要求的设计。根据 RFC [RFC7231],您可以找到 here 建议不要在 PUT 方法中更新部分内容。
"An origin server that allows PUT on a given target resource MUST send a 400 (Bad Request) response to a PUT request that contains a Content-Range header field (Section 4.2 of [RFC7233]), since the payload is likely to be partial content that has been mistakenly PUT as a full representation. Partial content updates are possible by targeting a separately identified resource with state that overlaps a portion of the larger resource, or by using a different method that has been specifically defined for partial updates (for example, the PATCH method defined in [RFC5789])."
首选解决方案是使用 PATCH 方法而不是 PUT。打补丁的方法在RFC中的thislink中有描述。部分资源修改引入了 PATCH 方法
所以查找 PATCH 方法,或者如果您想使用 PUT 可能有一个单独的端点,它只采用两个值之一。
可以找到有关 PATCH 方法的更多信息here
因此,要么采用 PATCH 方法,要么创建不同的模型和端点来满足使用 PUT 的部分更新。