我有一个LINQ-to-SQL对象,它序列化为XML没有任何问题。我可以调用Newtonsoft.Json.JsonConvert.SerializeObject(),我得到JSON结果。当我在WebAPI中传递与对象相同的结果时,我得到一个错误(见下文)。我建立了一个跟踪写入器来捕获null内部异常路径,我不确定如何找出导致错误的项目,如果路径是"?
20130301122959: Started serializing AnvilDB.Partner. Path ''.
20130301122959: Error serializing AnvilDB.Partner. An item with the same key has already been added. Path ''.
Error: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.CreateTypeInformation(Type type)
at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.GetTypeInformation(Type type)
at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.GetMetadataForProperty(Func`1 modelAccessor, Type containerType, String propertyName)
at System.Web.Http.Validation.ModelValidationRequiredMemberSelector.IsRequiredMember(MemberInfo member)
at System.Net.Http.Formatting.JsonContractResolver.ConfigureProperty(MemberInfo member, JsonProperty property)
at System.Net.Http.Formatting.JsonContractResolver.CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateProperties(Type type, MemberSerialization memberSerialization)
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType)
at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
20130301123002: Started serializing System.Web.Http.HttpError. Path ''.
20130301123002: Started serializing System.Web.Http.HttpError. Path 'InnerException'.
20130301123002: Finished serializing System.Web.Http.HttpError. Path 'InnerException'.
20130301123002: Finished serializing System.Web.Http.HttpError. Path ''.
深入研究后,我发现可以为序列化器设置一个错误处理程序,然后检查ErrorContext。成员的价值。这指向一个XElement类型的属性。进一步搜索发现这是一个已知/报告的错误,但尚未修复;见https://github.com/JamesNK/Newtonsoft.Json/issues/53
摘要:如果你有一个带有空值的XElement属性,JSON。净失败。
下面是我为诊断根本原因添加的内容:
base.Configuration.Formatters.JsonFormatter.SerializerSettings.Error = (sender, args) =>
{
string e = string.Format("{0}: {1}", args.ErrorContext.Member, args.ErrorContext.Path, args.ErrorContext.Error.Message);
myTracer.Trace(System.Diagnostics.TraceLevel.Error, e, args.ErrorContext.Error);
};
myTracer是一个简单的文件跟踪写入器。
我现在已经找到了解决这个bug的方法。
WebAPI用来序列化JSON对象的类不是直接来自JSON。. NET,但被设置为JsonContractResolver的实例,该实例位于System.Net.Http.Formatting中。幸运的是,这是开源的,所以您可以在这里看到当前版本:http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/4764b0111b91 src/System.Net.Http.Formatting/格式化/JsonContractResolver.cs
我将这段代码复制到我自己的类中,并将契约解析器替换为JSON。NET与我自己的类,使用这段代码(未更改)和错误被修复。由此我得出的结论是,当前发布的WebAPI版本(System.Net.Http。格式化版本4.0.20710.0)有这个错误,下一个版本可能会修复这个问题。
如果你像我一样需要现在修复它,下面是步骤:
- 使用JsonContractResolver.cs代码创建自己的契约解析器类
- 更改启动配置以覆盖ContractResolver设置:
var settings = System.Web.Http.GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
// create formatter
var formatter = new System.Net.Http.Formatting.JsonMediaTypeFormatter();
settings.ContractResolver = new MyJsonContractResolver(formatter);
这看起来像是Web API中的一个bug。我建议在这里提交一个bug:
http://aspnetwebstack.codeplex.com/workitem/list/basic同时,我认为你可以通过这样设置你的配置来解决这个问题:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();