2013-01-12 55 views
4

試圖利用System.Web.Http.OData.Delta在ASP.NET Web API服務中實現PATCH方法,但似乎無法將更改應用於類型爲IEnumerable<T>的屬性。我正在使用Delta的最新Git修訂版(2012.2-rc-76-g8a73abe)。有沒有人能夠做到這一點?如何使用System.Web.Http.OData.Delta修補枚舉?

考慮這個數據類型,它應該有可能在一個PATCH請求發送到Web API服務來更新:通過Delta<Person>

此Web API方法實現了一個人的修補:

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

如果我向服務發送帶有以下JSON的PATCH請求,則應該更新此人的Friends屬性,但可惜它不會發生:

{"Friends": [1]} 

問題的癥結在於如何讓Delta更新Friends這個數據。另請參閱discussion at CodePlex

回答

3

的問題可能是,德塔會嘗試分配JSON的JArrayHashset<int>

如果您使用的是它針對JsonMEdiaTypeFormatter和你內在三角洲代碼(這意味着你可以修改它),你必須做這樣的事情(這是粗糙的,但工程):

裏面的Delta<T>bool TrySetPropertyValue(string name, object value),它返回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; } 
    } 

而且你能夠成功地更新它們。

+0

謝謝你,你讓我很快樂(再次)!爲了使它工作,我不得不大幅改變你的代碼。 – aknuds1

+0

謝謝,好吧,我沒有直接在這裏輸入:) –

0

如果您使用的ODataMediaTypeFormatter,這應該工作。雖然有幾個警告提及。 1)您的收藏必須可以設置。 2)整個集合被替換。你不能刪除/添加個別元素。

此外,還有1項問題跟蹤 - '670 -Delta should support non-settable collections.'

+0

不,我正在使用JsonMediaTypeFormatter,無論Web API的默認值是什麼,因爲我只直接插入了Delta而沒有做任何其他更改。使用ODataMediaTypeFormatter有什麼特別的注意事項嗎?它是否以任何特定的方式改變我的API? – aknuds1

+1

我在哪裏可以找到有關使用ODataMediaTypeFormatter而不是JsonMediaTypeFormatter的信息? – aknuds1

+0

亞歷克斯詹姆斯[博客](http://blogs.msdn.com/b/alexj/archive/2012/12/07/odata-in-webapi-rc-release.aspx)有真正好的信息使用odap with webapi 。 –

1

您可以覆蓋Delta類的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); 
    } 
}