使用OpenType发回JObject时出错

时间:2014-12-02 15:06:48

标签: c# asp.net-web-api json.net

我为我的Web API http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/use-open-types-in-odata-v4实现了OpenType。我可以为此Property发送回字符串,int,数组等随机值。但是,尝试发送回JObject失败并出现错误 我怎样才能发回JObject?

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
Server: Microsoft-IIS/8.0
OData-Version: 4.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcQ29uZmlndXJhdGlvblxDb25maWd1cmF0aW9uU3RvcmVcQ29uZmlndXJhdGlvblNlcnZpY2UuQXBpXGFwaVxTZXJ2aWNlcygnRW5jb2RpbmcnKVxDb25maWd1cmF0aW9ucw==?=
X-Powered-By: ASP.NET
Date: Tue, 02 Dec 2014 14:56:01 GMT
Content-Length: 4046

{
  "error":{
    "code":"","message":"An error has occurred.","innererror":{
      "message":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal; odata.streaming=true'.","type":"System.InvalidOperationException","stacktrace":"","internalexception":{
        "message":"The given model does not contain the type 'Newtonsoft.Json.Linq.JObject'.","type":"System.InvalidOperationException","stacktrace":"   at System.Web.OData.Formatter.Serialization.ODataSerializerContext.GetEdmType(Object instance, Type type)\r\n   at System.Web.OData.Formatter.Serialization.ODataEdmTypeSerializer.AppendDynamicProperties(Object source, IEdmStructuredTypeReference structuredType, ODataSerializerContext writeContext, List`1 declaredProperties)\r\n   at System.Web.OData.Formatter.Serialization.ODataComplexTypeSerializer.CreateODataComplexValue(Object graph, IEdmComplexTypeReference complexType, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataComplexTypeSerializer.CreateODataValue(Object graph, IEdmTypeReference expectedType, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataCollectionSerializer.CreateODataCollectionValue(IEnumerable enumerable, IEdmTypeReference elementType, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataCollectionSerializer.CreateODataValue(Object graph, IEdmTypeReference expectedType, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEdmTypeSerializer.CreateProperty(Object graph, IEdmTypeReference expectedType, String elementName, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralPropertyBag(IEnumerable`1 structuralProperties, EntityInstanceContext entityInstanceContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"
      }
    }
  }
}

以下是一些可能有用的细节

班级定义

public sealed class Configuration
{
    public string ID { get; set; }
    public ConfigurationValue[] Values
    {
        get;
        set;
    }
}

public sealed class ConfigurationValue
{
    public IDictionary<string, object> ScopedValue { get; set; }
}

在控制器中,如果我按如下方式创建对象,则可以正常工作

var config = new Configuration{ ID="1", Values = new [] { new ConfigurationValue { ScopedValue = new Dictionary<string, object> {{"Val","1"}}}}};

但是,如果我执行以下操作就会爆炸

var value=JsonConvert.DeserializeObject(@"{'RetryInterval': 60,'MaxRetryCount': 100}");
var config = new Configuration{ ID="1", Values = new [] { new ConfigurationValue { ScopedValue = new Dictionary<string, object> {{"Val",value}}}}};

1 个答案:

答案 0 :(得分:3)

问题根本没有在您发布的代码中,它运行得很完美。问题是OData无法与您的班级合作。

OData不支持所有类型,更明确地它不支持没有setter和getter的类型

Dictionary基本上是KeyValuePair个对象的列表。 KeyValuePair使用索引,但没有get;set;

解决方案是使用包含两个属性的普通类,并将它们放在List中,而不是使用Dictionary

public class ScopedValue
{
    public string Key { get; set; }
    public object Value { get; set; }
}

public sealed class ConfigurationValue
{
    public List<ScopedValue> ScopedValues { get; set; }
}