Asp.net web api 在Web Api 2中,从OData客户端调用补丁的正确方法是什么

Asp.net web api 在Web Api 2中,从OData客户端调用补丁的正确方法是什么,asp.net-web-api,odata,Asp.net Web Api,Odata,根据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); myD

根据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);
}
但是,通过跟踪fiddler中的调用,我看到Foo的所有其他属性都被序列化并发送到服务。这是正确的行为吗?我只希望通过网络发送Id和描述。另外,如果我调试服务方法并调用

GetChangedPropertyNames
在项上,返回其所有属性名

我应该在客户机上创建某种增量实例吗

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

更新 提供的链接YiDing解释了如何从客户端创建真正的修补程序请求(使用由Microsoft.OData.client.DataServiceContext创建的
Microsoft.OData.client 6.2.0
及更高版本)。 为方便起见,以下是代码片段:

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();

尽管文档与此相反,但所有属性仍然通过网络发送,至少从Microsoft.OData.Client 6.7.0开始,Microsoft.OData.Client 6.2.0版本现在支持客户端属性跟踪。它将仅检测实体的修改属性,并将更新请求作为补丁发送,而不是pUT以满足您的场景要求。有关更多详细信息,请参阅本博客文章:

当使用补丁amd delta时,我们只在JSON有效负载中发布我们想要更改的属性。看起来您在示例代码中提交了一个完整的foo对象?@eoghank我尝试过创建对象的空实例和只设置Id和所选属性的几种变体,但是(使用自动生成的DataServiceContext)我无法在没有运行时异常的情况下提交已被客户端上下文跟踪或未被客户端上下文跟踪的实体…您是否尝试过使用其他带有json或httpclient的客户端?我不知道自动生成的wcf客户端代理是否支持修补程序/增量。确切地说…我的问题是针对自动生成的客户端及其derived
DataServiceContext
。我见过使用“手动”构造的帖子正文的示例。同样,上面的示例来自团队自己发布的CodePlex上的Web API示例应用程序。因此,他们努力展示了如何使用补丁而不是put,但我感到困惑的是,这种行为并不像宣传的那样。对于大型实体,为小型属性更新瘦身有效负载可能很有用。在我阅读链接文章之前,这需要花费很长时间才能解决。这里的关键是使用
DataServiceCollection
包装器。没有它,整个实体始终被发送。
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();
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();