此問題影響我的ASP.Net的WebAPI修補方法,它看起來很像是:Json.Net DeserializeObject與OData.Delta失敗 - 只能爲整數
public MyModel Patch(int id, [FromBody]Delta<MyModel> newRecord){/*stuff here*/}
但它不是的WebAPI這就是問題所在 - 失敗介於Json.Net和OData.Delta之間。
問題是JsonConvert.DeserializeObject看不到OData.Delta對象的整數,我想知道是否有我可以應用的解決方法或修復。
更新:在Json.Net庫中已經編寫了代碼(參見下面的右邊)來解決這個問題。只需要它被包括在下一次更新(如果詹姆斯牛頓 - 金允許它)
更新2:經過進一步測試,我決定最好的行動方針是停止使用OData.Delta和寫我自己的(見答案)
單元測試來證明問題的存在(使用下面的語句移動爲清楚起見)
測試1:無法與一個int(的Int32):
class TestObjWithInt
{
public int Int { get; set; }
}
[TestMethod]
public void IsApplied_When_IntIsDeserializedToDelta()
{
string testData = "{\"Int\":1}";
var deserializedDelta = JsonConvert.DeserializeObject<Delta<TestObjWithInt>>(testData);
var result = deserializedDelta.GetChangedPropertyNames().Contains("Int");
Assert.IsTrue(result);
}
特ST 2:用長(Int64的)成功
class TestObjWithLong
{
public long Long { get; set; }
}
[TestMethod]
public void IsApplied_When_LongIsDeserializedToDelta()
{
string testData = "{\"Long\":1}";
var deserializedDelta = JsonConvert.DeserializeObject<Delta<TestObjWithLong>>(testData);
var result = deserializedDelta.GetChangedPropertyNames().Contains("Long");
Assert.IsTrue(result);
}
而只是爲了確保反序列化工作開始說起,這兩個測試都通過。
[TestMethod]
public void IsApplied_When_LongIsDeserializedToTestObject()
{
string testData = "{\"Long\":1}";
var deserializedObject = JsonConvert.DeserializeObject<TestObjWithLong>(testData);
var result = deserializedObject.Long == 1;
Assert.IsTrue(result);
}
[TestMethod]
public void IsApplied_When_IntIsDeserializedToTestObject()
{
string testData = "{\"Int\":1}";
var deserializedObject = JsonConvert.DeserializeObject<TestObjWithInt>(testData);
var result = deserializedObject.Int == 1;
Assert.IsTrue(result);
}
我發現this OData的bug報告這聽起來像一個類似的問題,但它的老所以大概不會關閉。
任何幫助將是偉大的。
using語句(從測試文件的頂部):
using System;
using System.Linq;
using System.Web.Http.OData;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
如果接受詹姆斯·牛頓王解決方案 - 改變釋放6.0.6。 更換JsonSerializerInternalReader.cs線1581:
contract.TrySetMember(newObject, memberName, value);
有:
bool done = false;
while (!(done = done || contract.TrySetMember(newObject, memberName, value)))
{
switch (reader.TokenType)
{
case JsonToken.Integer:
if (value is long && ((long)value) <= Int32.MaxValue && ((long)value) >= Int32.MinValue)
value = Convert.ToInt32(value);
//Add else if (...) to cast to other data types here (none additional required to date).
else
done = true;
break;
default:
done = true;
break;
}
}
在情況下,它可以幫助任何人,有一個非常類似的問題,我已經有了一個更簡單,更「黑客」修復線程。 [這是答案。](http://stackoverflow.com/a/41749206/2283050) – 2017-01-19 19:14:51