[英]How to PATCH in Web API and OData
通过阅读Patch动词的RFC规范,很明显Patch
动词不应该获得部分更新实体的值,而是要进行的操作:
但是,使用PATCH,随附的实体包含一组指令,描述如何修改当前驻留在源服务器上的资源以生成新版本。
在MSDN中,对于Delta类,它也很清楚,因为Patch描述说:
使用此Delta 跟踪的更改覆盖原始实体。
与Put的描述不同:
使用存储在此Delta中的值覆盖原始实体。
到目前为止一切都那么好,但我找不到用OData发送这些“指令”的方法,无论我做什么,Delta.Patch只替换值。
补丁请求的语法应该是什么?
我尝试的方式是:
PATCH http://localhost:55783/Products(1) HTTP/1.1
User-Agent: Fiddler
Host: localhost:55783
Content-Length: 19
Content-type: application/json
{ "Price": 432 }
和
{ "op": "add", "path": "/Price", "value": 423432 }
那附近的东西。
更新:
感谢迈克尔·摩尔和用ILSpy阅读整个Delta课程,我认为这确实是Patch动词设计中的一个错误。
我为微软公开了一个错误,如果您需要修复它,可以对它进行投票。
我不确定你想要达到的目标是可能的。 至少没有Delta<TEntity>.Patch(..)
假设您拥有Product
实体并且在PATCH
操作中的某个位置
[AcceptVerbs("PATCH")]
public void Patch(int productId, Delta<Product> product)
{
var productFromDb = // get product from db by productId
product.Patch(productFromDb);
// some other stuff
}
创建product
,它在内部调用Delta<TEntityType>
构造函数,它看起来像这样(无参数构造函数也调用这个,传递typeof(TEntityType)
public Delta(Type entityType)
{
this.Initialize(entityType);
}
Initialize
方法看起来像这样
private void Initialize(Type entityType)
{
// some argument validation, emitted for the sake of brevity
this._entity = (Activator.CreateInstance(entityType) as TEntityType);
this._changedProperties = new HashSet<string>();
this._entityType = entityType;
this._propertiesThatExist = this.InitializePropertiesThatExist();
}
有趣的部分是this._propertiesThatExist
,它是Dictionary<string, PropertyAccessor<TEntityType>>
,它包含Product类型的属性。 PropertyAccessor<TEntityType>
是内部类型,可以更轻松地操作属性。
当你调用product.Patch(productFromDb)
这就是product.Patch(productFromDb)
发生的事情
// some argument checks
PropertyAccessor<TEntityType>[] array = (
from s in this.GetChangedPropertyNames()
select this._propertiesThatExist[s]).ToArray<PropertyAccessor<TEntityType>>();
PropertyAccessor<TEntityType>[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
PropertyAccessor<TEntityType> propertyAccessor = array2[i];
propertyAccessor.Copy(this._entity, original);
}
正如您所看到的,它获取了已更改的属性,对它们进行迭代并将值从传递给Patch操作的实例设置为从db获取的实例。 因此,您要传递的操作,属性名称和要添加的值不会反映任何内容。
propertyAccessor.Copy(this._entity, original)
方法的正文
public void Copy(TEntityType from, TEntityType to)
{
if (from == null)
{
throw Error.ArgumentNull("from");
}
if (to == null)
{
throw Error.ArgumentNull("to");
}
this.SetValue(to, this.GetValue(from));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.