5

オブジェクトを部分的に更新するために HttpPatch を使用しています。それを機能させるために、OData の Delta および Patch メソッドを使用しています (ここで言及: Web API で部分的な更新を実行する現在推奨される方法は何ですか? )。すべてが正常に機能しているように見えますが、マッパーは大文字と小文字を区別することに気付きました。次のオブジェクトが渡されると、プロパティは更新された値を取得します:

{
  "Title" : "New title goes here",
  "ShortDescription" : "New text goes here"
}

しかし、同じオブジェクトを下位またはキャメルケースのプロパティで渡すと、パッチが機能しません。新しい値が通過しないため、逆シリアル化とプロパティのマッピングに問題があるようです。つまり、「shortDescription」から「ShortDescription」へ"。

Patch を使用して大文字と小文字を区別しない構成セクションはありますか?

ご参考までに:

出力には、次のフォーマッタを使用して (REST のベスト プラクティスに従って) キャメル ケースのプロパティがあります。

//formatting
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SerializerSettings = jss;

//sample output
{
  "title" : "First",
  "shortDescription" : "First post!"
}

ただし、私のモデル クラスは C#/.NET の書式設定規則に従っています。

public class Entry {
  public string Title { get; set;}
  public string ShortDescription { get; set;}
  //rest of the code omitted
}
4

2 に答える 2

3

これは、CamelCasePropertyNamesContractResolver を継承するカスタム コントラクト リゾルバーと、json から取得したものを使用する代わりに、デルタの具象型を調べて実際のプロパティ名を取得する CreateContract メソッドを実装することで、非常に簡単に実行できます。アブストラクトは以下です。

public class DeltaContractResolver : CamelCasePropertyNamesContractResolver
{
        protected override JsonContract CreateContract(Type objectType)
        {
            // This class special cases the JsonContract for just the Delta<T> class. All other types should function
            // as usual.
            if (objectType.IsGenericType &&
                objectType.GetGenericTypeDefinition() == typeof(Delta<>) &&
                objectType.GetGenericArguments().Length == 1)
            {
                var contract = CreateDynamicContract(objectType);
                contract.Properties.Clear();

                var underlyingContract = CreateObjectContract(objectType.GetGenericArguments()[0]);
                var underlyingProperties =
                    underlyingContract.CreatedType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (var property in underlyingContract.Properties)
                {
                    property.DeclaringType = objectType;
                    property.ValueProvider = new DynamicObjectValueProvider()
                    {
                        PropertyName = this.ResolveName(underlyingProperties, property.PropertyName),
                    };

                    contract.Properties.Add(property);
                }

                return contract;
            }

            return base.CreateContract(objectType);
        }

        private string ResolveName(PropertyInfo[] properties, string propertyName)
        {

            var prop = properties.SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));

            if (prop != null)
            {
                return prop.Name;
            }

            return propertyName;
        }
}
于 2014-10-15T19:49:27.657 に答える