8

Patch 動詞の RFC 仕様を読むと、Patch動詞がエンティティを部分的に更新するための値を取得するのではなく、操作を行う必要があることが明らかです。

...ただし、PATCH を使用すると、囲まれたエンティティには、現在オリジン サーバーに存在するリソースを変更して新しいバージョンを生成する方法を説明する一連の指示が含まれます。

パッチの説明にあるように、デルタクラスのMSDNでも明らかです。

このデルタによって追跡される変更で元のエンティティを上書きします。

Putの説明とは異なり:

このデルタに格納されているで元のエンティティを上書きします。

ここまではうまくいきましたが、これらの「指示」を 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 動詞設計のバグだと思います。
Microsoft のバグをオープンしました。修正が必要な場合は、投票してください。

4

1 に答える 1

13

あなたが達成しようとしていることが可能かどうかはわかりません。少なくとも一緒ではない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._propertiesThatExistDictionary<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 から取得したインスタンスに設定します。したがって、渡す操作、追加するプロパティ名と値には何も反映されません。

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));
}
于 2014-09-01T23:25:51.533 に答える