在Web Api 2中从OData客户端调用补丁的正确方法是什么

时间:2014-01-28 17:16:33

标签: 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);
  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,返回其所有属性名称。

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

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

更新

YiDing提供的链接说明了如何从客户端创建真正的PATCH请求(使用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();

DataServiceCollection实现属性跟踪,并使用此模式,仅将更新的属性发送到服务。 不使用DataServiceCollection而只是使用

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

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

1 个答案:

答案 0 :(得分:5)

现在,Microsoft.OData.Client版本6.2.0支持客户端属性跟踪。它将仅检测实体的已修改属性,并将更新请求作为PATCH而不是PUT发送,以满足您的方案的要求。有关更多详细信息,请参阅此博客文章: http://blogs.msdn.com/b/odatateam/archive/2014/04/10/client-property-tracking-for-patch.aspx