部分实体更新中的WebAPI PUT / POST(Partial Entity Updates i

2019-08-31 16:51发布

假设你有一个存储库的方法来更新文档:

public Document UpdateDocument(Document document)
  {
  Document serverDocument = _db.Documents.Find(document.Id);
  serverDocument.Title = document.Title;
  serverDocument.Content = document.Content;
  _db.SaveChanges();
  return serverDocument;
  }

在这种情况下,该实体有两个属性。 当更新一个文件,这两种性质都需要在JSON请求,因此请求PUT /api/folder与身体的

{
  "documentId" = "1",
  "title" = "Updated Title"
}

因为“内容”并没有规定将返回一个错误。 我这样做的原因是因为,即使是空的属性和属性,用户不更新,它似乎更安全强制客户端中,以避免覆盖与空服务器端未指定领域的要求,指定这些字段。

这导致我总是需要在PUT和POST请求的每个更新的财产,即使这意味着这些属性指定空的做法。

这是很酷的,或者是有一个模式/实践中,我还没有了解还可能方便必要的东西通过网络发送的部分更新?

Answer 1:

在API设计的最佳实践是使用HTTP PATCH的部分更新。 事实上,使用像你这样的情况是,为什么IETF首先介绍了它的真正原因。

RFC 5789定义它非常精确:

补丁是用于局部修改应用到的资源。

一种新的方法是必要的,以提高互操作性和预防
错误。 PUT方法已经被定义来覆盖资源
具有完整的新机构,而不能再用做局部修改 。 否则,代理和缓存,甚至客户端和服务器,可以得到
困惑,所述操作的结果。 POST已被使用,但没有广泛的互操作性(为一体,没有标准的方式来
发现补丁格式支持)。

马克诺丁汉写关于API设计中使用PATCH的大文章 - http://www.mnot.net/blog/2012/09/05/patch

在你的情况,这将是:

  [AcceptVerbs("PATCH")]
  public Document PatchDocument(Document document)
  {
      Document serverDocument = _db.Documents.Find(document.Id);
      serverDocument.Title = document.Title;
      serverDocument.Content = document.Content;
      _db.SaveChanges();
      return serverDocument;
  }


Answer 2:

这是很酷的,或者是有一个模式/实践中,我还没有了解还可能方便必要的东西通过网络发送的部分更新?

做的好的做法POSTPUT是只包括您需要的特定要求值。 在做UpdateDocument你应该问自己什么是“真应该在这里完成”? 如果你有一百个字段对象上你需要更新所有的或只是其中的一部分。 什么“动作”你真的想要吗?

让我们对这些问题的一个例证,说我们有一个User具有以下字段的对象:

public class User {
    public int Id {get;set;}
    public string Username {get;set;}
    public string RealName {get;set;}
    public string Password {get;set;}
    public string Bio {get;set;}
}

然后,您有两个用例:

  1. 更新用户的配置文件
  2. 更新用户的密码

当你每次那些你不会,或者这是一个好主意,有一个更新的方法,将两者都做。 相反,有一个通用的UpdateUser方法,你应该有以下几种方法:

  1. UpdateProfile
  2. UpdatePassword

方法接受,他们只需要领域,仅此而已,无所不及。

public User UpdateProfile(int id, string username, string realname, string bio) {
}
public User UpdatePassword(int id, string password) {
}

现在问题来了:

我有一个使用案例,一个“用户行为”允许在多个领域的更新,其中一些字段可以由用户“无输入”,但我不想更新我的模型场。

假设一个用户更新他/她的个人资料和提供的值UsernameRealName而不是Bio 。 但你不希望设置Bio为null或空,如果它有一个值了。 那么它将成为您的应用程序的业务逻辑的一部分,并应明确处理

public User UpdateProfile(int id, string username, string realname, string bio) {
    var user = db.Users.Find(id);
    // perhaps a validation here (e.g. if user is not null)
    user.Username = username;
    user.RealName = realname;
    if (!string.IsNullOrEmptyWHiteSpace(bio)) {
        user.Bio = bio;
    }
}


文章来源: Partial Entity Updates in WebAPI PUT/POST