C# ModelState错误-Newtonsoft.Json.JsonSerializationException:无法填充列表类型System.Net.TrackingString目录
当一个用户试图调用webApi时,标题中出现了错误。 这是我的班级:C# ModelState错误-Newtonsoft.Json.JsonSerializationException:无法填充列表类型System.Net.TrackingString目录,c#,.net,asp.net-web-api,json.net,C#,.net,Asp.net Web Api,Json.net,当一个用户试图调用webApi时,标题中出现了错误。 这是我的班级: public class NotificationDTO { public long idCompanyService { get; set; } public DocTypeEnum DocumentType { get; set; } public List<Tuple<string, byte[], System.Net.Mime.ContentType>> Attac
public class NotificationDTO
{
public long idCompanyService { get; set; }
public DocTypeEnum DocumentType { get; set; }
public List<Tuple<string, byte[], System.Net.Mime.ContentType>> Attachments { get; set; }
}
这就是电话:
HttpContent content = new StringContent(JsonConvert.SerializeObject(notifDto), Encoding.UTF8, "application/json");
HttpResponseMessage response = client.PostAsync(uri, content).Result;
这是一个Json:
{"idCompanyService":1234,"DocumentType":0,"Attachments":[{"Item1":"test.pdf","Item2":"ThisIsABase64Data","Item3":{"Boundary":null,"CharSet":null,"MediaType":"application/pdf","Name":null,"Parameters":[]}}}
附件有问题,因为它是一个列表
错误消息:
Exception: Newtonsoft.Json.JsonSerializationException: Cannot populate list type System.Net.TrackingStringDictionary. Path 'Attachments.$values[0].Item3.Parameters.$values', line 1, position 105257.
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
in Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
试一试:
您可以使用简单的web api控制器再现错误:
[HttpPost]
[Route("api/TestNotification")]
public IHttpActionResult TestNotification(NotificationDTO dto)
{
return Ok();
}
Post调用程序中的Json如下所示:
{"idCompanyService":1234,"DocumentType":1,"Attachments":[{"Item1":"wqere.pdf","Item2":"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=","Item3":{"Boundary":null,"CharSet":null,"MediaType":"application/pdf","Name":null,"Parameters":[]}},{"Item1":"ewqeqwe.xml","Item2":"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=","Item3":{"Boundary":null,"CharSet":null,"MediaType":"text/xml","Name":null,"Parameters":[]}}]}
最后,一个.Net fiddle演示了将上述JSON字符串反序列化为NotificationDTO
时的失败,通过:
var dto = JsonConvert.DeserializeObject<NotificationDTO>(json);
var dto=JsonConvert.DeserializeObject(json);
可以在这里找到:。这里真正的问题是DTO引用类型为的对象,而该对象又有一个声明类型(和实际类型)的成员。 不幸的是,这种古老的类型(来自.NET1.1)甚至没有实现
IDictionary
。由于Json.NET只实现非类型化枚举器System.Collections.IEnumerable
,因此它无法知道如何对其进行反序列化,并在请求时抛出您看到的异常
因此,有必要编写一个程序来反序列化此类型的对象或从该类型派生的对象:
using System.Collections.Specialized;
public class StringDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(StringDictionary).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var tokenType = reader.SkipComments().TokenType;
if (tokenType == JsonToken.Null)
return null;
var dictionary = existingValue as StringDictionary ?? (StringDictionary)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
switch (tokenType)
{
case JsonToken.StartArray:
{
// StringDictionary serialized without converter
var list = serializer.Deserialize<List<KeyValuePair<string, string>>>(reader);
foreach (var pair in list)
dictionary.Add(pair.Key, pair.Value);
}
break;
case JsonToken.StartObject:
{
// StringDictionary serialized with converter
var typedDictionary = serializer.Deserialize<Dictionary<string, string>>(reader);
foreach (var pair in typedDictionary)
dictionary.Add(pair.Key, pair.Value);
}
break;
default:
throw new JsonSerializationException(string.Format("Unknown token {0} at path {1}", tokenType, reader.Path));
}
return dictionary;
}
// Change to false if you want the dictionary written as an array of key/value objects.
public override bool CanWrite { get { return true; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dictionary = (StringDictionary)value;
writer.WriteStartObject();
foreach (DictionaryEntry entry in dictionary)
{
writer.WritePropertyName((string)entry.Key);
writer.WriteValue((string)entry.Value);
}
writer.WriteEndObject();
}
}
public static partial class JsonExtensions
{
public static JsonReader SkipComments(this JsonReader reader)
{
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
}
JsonSerializerSettings
,并添加一个StringDictionaryConverter
,如上所示小提琴样品。请您将问题分享给我们,好吗?在这种情况下,我认为为
NotificationDTO
、反序列化代码和示例JSON定义就足够了。您的错误消息似乎很好,在尝试序列化System.Net时,在字符位置105257处序列化失败。TrackingStringDictionary
-并非所有类型都可以转换为JSON。顺便说一下,这是一个相当大的数字,看起来您正在发送文件数据?如果看不到你的结构,很难说。好吧,我编辑了我的问题@dbct,但这不是一个真正的问题。异常发生在哪一行?是在HttpContent content=newstringcontent(JsonConvert.SerializeObject(notifDto),Encoding.UTF8,“application/json”)代码>或位于httpresponsemessageresponse=client.PostAsync(uri,content.Result)代码>?如何在一个简单的控制台应用程序中重现该问题?消息中没有行号。当我调用WebApi时,在第一行到达之前,将异常抛出到日志文件中。
using System.Collections.Specialized;
public class StringDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(StringDictionary).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var tokenType = reader.SkipComments().TokenType;
if (tokenType == JsonToken.Null)
return null;
var dictionary = existingValue as StringDictionary ?? (StringDictionary)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
switch (tokenType)
{
case JsonToken.StartArray:
{
// StringDictionary serialized without converter
var list = serializer.Deserialize<List<KeyValuePair<string, string>>>(reader);
foreach (var pair in list)
dictionary.Add(pair.Key, pair.Value);
}
break;
case JsonToken.StartObject:
{
// StringDictionary serialized with converter
var typedDictionary = serializer.Deserialize<Dictionary<string, string>>(reader);
foreach (var pair in typedDictionary)
dictionary.Add(pair.Key, pair.Value);
}
break;
default:
throw new JsonSerializationException(string.Format("Unknown token {0} at path {1}", tokenType, reader.Path));
}
return dictionary;
}
// Change to false if you want the dictionary written as an array of key/value objects.
public override bool CanWrite { get { return true; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dictionary = (StringDictionary)value;
writer.WriteStartObject();
foreach (DictionaryEntry entry in dictionary)
{
writer.WritePropertyName((string)entry.Key);
writer.WriteValue((string)entry.Value);
}
writer.WriteEndObject();
}
}
public static partial class JsonExtensions
{
public static JsonReader SkipComments(this JsonReader reader)
{
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
}
protected void Application_Start()
{
var config = GlobalConfiguration.Configuration;
var settings = config.Formatters.JsonFormatter.SerializerSettings;
settings.Converters.Add(new StringDictionaryConverter());
}