如何修补与可枚举System.Web.Http.OData.Delta?(How do I patc

2019-08-06 13:44发布

试图利用System.Web.Http.OData.Delta实现PATCH中的ASP.NET Web API服务的方法,但似乎无法更改应用到类型的属性IEnumerable<T> 我使用的是台达(2012.2-RC-76-g8a73abe)的最新版本的Git。 任何人都已经能够使这项工作?

考虑这个数据类型,它应该可以在一个PATCH请求的Web API服务更新:

public class Person
{
    HashSet<int> _friends = new HashSet<int>();

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public IEnumerable<int> Friends
    {
        get { return _friends; }
        set
        {
            _friends = value != null ? new HashSet<int>(value) : new HashSet<int>();
        }
    }

    public Person(int id, string firstName, string lastName)
    {
        Id = id;
        FirstName = firstName;
        LastName = lastName;
    }

    public Person()
    {
    }
}

此Web API方法实现通过一个人的修补Delta<Person>

public void Patch(int id, Delta<Person> delta)
{
    var person = _persons.Single(p => p.Id == id);
    delta.Patch(person);
}

如果我返回以下JSON补丁请求到服务,人的Friends属性应被更新,但可惜它不会发生:

{"Friends": [1]}

而问题的关键是如何真正做增量更新Friends与此数据。 另见在CodePlex上讨论 。

Answer 1:

这个问题可能是德塔将尝试JSON的分配JArrayHashset<int>

如果您使用的是它针对JsonMEdiaTypeFormatter和你内在三角洲代码(这意味着你可以修改它),你必须做这样的事情(这是粗糙的,但工程):

内, bool TrySetPropertyValue(string name, object value)Delta<T>在那里它返回false:

        if (value != null && !cacheHit.Property.PropertyType.IsPrimitive && !isGuid && !cacheHit.Property.PropertyType.IsAssignableFrom(value.GetType()))
        {
           return false;
        }

改成:

var valueType = value.GetType();
var propertyType = cacheHit.Property.PropertyType;
if (value != null && !propertyType.IsPrimitive && !propertyType.IsAssignableFrom(valueType))
{
    var array = value as JArray;
    if (array == null)
        return false;

    var underlyingType = propertyType.GetGenericArguments().FirstOrDefault() ??
        propertyType.GetElementType();
    if (underlyingType == typeof(string))
    {
        var a = array.ToObject<IEnumerable<string>>();
        value = Activator.CreateInstance(propertyType, a);
    }
    else if (underlyingType == typeof(int))
    {
        var a = array.ToObject<IEnumerable<int>>();
        value = Activator.CreateInstance(propertyType, a);
    }
    else
        return false;
}

这只有在集合工作intstring ,但希望你轻推到一个很好的方向。

例如,现在你的模型有:

public class Team {
        public HashSet<string> PlayerIds { get; set; }
        public List<int> CoachIds { get; set; }
    }

而且你能够成功地更新它们。



Answer 2:

您可以覆盖TrySetPropertyValue的方法三角洲类,并利用JArray类:

public sealed class DeltaWithCollectionsSupport<T> : Delta<T> where T : class
{
    public override bool TrySetPropertyValue(string name, object value)
    {
        var propertyInfo = typeof(T).GetProperty(name);

        return propertyInfo != null && value is JArray array
            ? base.TrySetPropertyValue(name, array.ToObject(propertyInfo.PropertyType))
            : base.TrySetPropertyValue(name, value);
    }
}


Answer 3:

如果您使用的是ODataMediaTypeFormatter,这应该是工作。 有几个需要注意的地方来,虽然提及。 1)您的收藏必须是可调节。 2)整个集合被替换。 你不能删除/添加单个元素。

此外,还有跟踪项目1个问题- “670 -Delta应该支持非设定的集合。”



文章来源: How do I patch enumerables with System.Web.Http.OData.Delta?