asp.net mvc web api partial update with OData Patch

后端 未结 2 1463
清歌不尽
清歌不尽 2021-02-06 14:03

I am using HttpPatch to partially update an object. To get that working I am using Delta and Patch method from OData (mentioned here: What's the currently recommended way of

2条回答
  •  死守一世寂寞
    2021-02-06 14:33

    It can be done quite easily with a custom contract resolver that inherits CamelCasePropertyNamesContractResolver and implementing CreateContract method that look at concrete type for delta and gets the actual property name instead of using the one that comes from json. Abstract is below:

    public class DeltaContractResolver : CamelCasePropertyNamesContractResolver
    {
            protected override JsonContract CreateContract(Type objectType)
            {
                // This class special cases the JsonContract for just the Delta 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;
            }
    }
    

提交回复
热议问题