gpt4 book ai didi

c# - 如何在 Web API 和 OData 中进行 PATCH

转载 作者:太空狗 更新时间:2023-10-29 18:22:05 26 4
gpt4 key购买 nike

来自阅读RFC specification of the Patch verb很明显,Patch 动词不应该获取值来部分更新实体,而是要执行以下操作:

...With PATCH, however, the enclosed entity contains a setof instructions describing how a resource currently residing on theorigin server should be modified to produce a new version.

在 Delta 类的 MSDN 中,它也很清楚,因为 Patch描述说:

Overwrites the original entity with the changes tracked by this Delta.

不像Put的描述:

Overwrites the original entity with the values stored in this 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 }

以及与之相近的东西。


更新:

感谢 Michael Moore 和使用 ILSpy 阅读了整个 Delta 类,我认为这确实是 Patch 动词设计中的一个错误。
I opened a bug for Microsoft, you can vote on it if you need it to be fixed too.

最佳答案

我不确定您要实现的目标是否可行。至少不是 Delta<TEntity>.Patch(..)

假设您有 Product实体和你的某个地方 PATCH你的 Action

[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) 时这就是引擎盖下发生的事情

// 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 获取的实例。因此,您传递的操作、要添加的属性名称和值不会反射(reflect)任何内容。

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

关于c# - 如何在 Web API 和 OData 中进行 PATCH,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25608240/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com