试图利用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上讨论 。
这个问题可能是德塔将尝试JSON的分配JArray
您Hashset<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;
}
这只有在集合工作int
或string
,但希望你轻推到一个很好的方向。
例如,现在你的模型有:
public class Team {
public HashSet<string> PlayerIds { get; set; }
public List<int> CoachIds { get; set; }
}
而且你能够成功地更新它们。
您可以覆盖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);
}
}
如果您使用的是ODataMediaTypeFormatter,这应该是工作。 有几个需要注意的地方来,虽然提及。 1)您的收藏必须是可调节。 2)整个集合被替换。 你不能删除/添加单个元素。
此外,还有跟踪项目1个问题- “670 -Delta应该支持非设定的集合。”