【问题标题】:What is the correct way to call patch from an OData client in Web Api 2从 Web Api 2 中的 OData 客户端调用补丁的正确方法是什么
【发布时间】:2014-02-20 03:34:30
【问题描述】:

根据 web api 团队创建的 OData 示例,我的控制器具有以下支持补丁:

public HttpResponseMessage Patch([FromODataUri] int key, Delta<Foo> item)
{
  var dbVersion = myDb.GetById(key);
  if(dbVersion == null)
    throw Request.EntityNotFound();

  item.Patch(dbVersion);
  myDb.Update(dbVersion);

  return Request.CreateResponse(HttpStatusCode.NoContent);
}

并使用自动生成的客户端(源自DataServiceContext),我提交了一个补丁请求,如下所示:

var foo = svcContainer.Foos.Where (f => f.Id == 1).SingleOrDefault();
foo.Description = "Updated Description";
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);

但是,在 fiddler 中跟踪调用,我看到 Foo 的所有其他属性都被序列化并发送到服务。这是正确的行为吗?我只希望通过网络发送 ID 和描述。另外,如果我调试服务方法并调用

GetChangedPropertyNames 在 item 上,返回其所有属性名称。

我应该在客户端上创建某种 Delta 实例吗?

我了解服务的断开连接性质,因此服务端没有用于跟踪更改的上下文,但是在我看来,api 团队添加了对补丁的支持是有原因的,所以我'想知道客户端是否应该以不同的方式调用更新。

更新

一丁提供的链接解释了如何从客户端创建一个真正的PATCH请求(使用Microsoft.OData.Client 6.2.0及以上创建的Microsoft.OData.Client.DataServiceContext。 为方便起见,这里是代码sn-p:

var svcContainer = new Default.Container(<svcUri>);
var changeTracker = new DataServiceCollection<Foo>(svcContainer.Foos.Where(f => f.Id == 1));
changeTracker[0].Description = "Patched Description";
svcContainer.SaveChanges();

DataServiceCollection 实现属性跟踪,并且使用这种模式,只有更新的属性会发送到服务。 不使用DataServiceCollection,只使用

svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();

尽管有相反的文档,但所有属性仍通过网络发送,至少截至Microsoft.OData.Client 6.7.0

【问题讨论】:

  • 使用 PATCH amd delta 时,我们只发布我们想要在 JSON 有效负载中更改的属性。看起来您在示例代码中提交了一个完整的 foo 对象?
  • @eoghank 我已经尝试了几种创建对象的空实例并仅设置 Id 和 selected 属性的变体,但是(使用自动生成的 DataServiceContext)我无法在没有运行时异常的情况下提交实体要么已经被客户端上下文跟踪,要么没有被客户端上下文跟踪......
  • 您是否尝试过使用不同的带有 json 或 httpclient 的客户端?不知道自动生成的wcf客户端代理是否支持patch/delta。
  • 正是...我的问题是特定于自动生成的客户端及其派生的DataServiceContext。我见过使用“手动”构建的帖子正文的示例。同样,上面的示例来自团队自己发布的 CodePlex 上的 Web API 示例应用程序。因此,他们努力展示了如何使用 patch 与 put,但我很困惑这种行为并不像宣传的那样。对于大型实体,为小型属性更新精简有效负载可能很有用。

标签: asp.net-web-api odata


【解决方案1】:

现在从 Microsoft.OData.Client 版本 6.2.0 开始支持客户端属性跟踪。它将仅检测实体的修改属性并将更新请求作为 PATCH 而不是 PUT 发送以满足您的场景要求。有关更多详细信息,请参阅此博客文章: https://devblogs.microsoft.com/odata/tutorial-sample-client-property-tracking-for-patch/

【讨论】:

  • 这花了很长时间才弄清楚,直到我阅读了链接的帖子。使用DataServiceCollection 包装器是这里的关键。没有这个,整个实体总是被发送。
  • 令人失望的是,这在文档中没有得到更多关注,补丁是一个关键的 OData 概念。可以自己执行此操作,但它需要 heavy DTO,其中 Self Tracking 内置在更改逻辑的属性中,或者您需要构建另一个 Tracking i> 自动侦听所有属性更改事件的上下文,因此它知道要在补丁中发送哪些属性。你会发现DataServiceCollection 是一个优雅的轻量级解决方案,适用于不需要大量修补的客户端应用程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 1970-01-01
  • 2014-10-25
相关资源
最近更新 更多