I am trying to return some data to a webservice using json and the JSon.Net library. One of my functions is an iterator method that lists data using yield return. When I try to serialize this return value, I am getting an invalid operation exception
I am using
string jsonEncoded = JsonConvert.SerializeObject(ret, Formatting.Indented);
to serialize the return value.
The full stack trace of the exception is:
System.InvalidOperationException: This operation is only valid on generic types.
at System.RuntimeType.GetGenericTypeDefinition()
at Newtonsoft.Json.Serialization.JsonArrayContract..ctor(Type underlyingType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonArrayContract.cs:line 148
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateArrayContract(Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 686
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 800
at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 232
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.GetContractSafe(Object value) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:line 83
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:line 67
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:line 753
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:line 668
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, Formatting formatting, JsonSerializerSettings settings) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 921
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 893
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 837
at AladdinWeb.Handlers.AladdinHandler.ProcessRequest(HttpContext context) in C:\Users\mehrlich\Projects\AladdinWeb\AladdinWeb\Server\Handlers\AladdinHandler.cs:line 85 [ 15/04/2013 11:24:24.68135 ]
The signature of the iterator method is:
public IEnumerable<dynamic> FunctionName() { ... }
As of now, I have a temporary solution in place by checking for calls to this function and calling ToList
on the return value. This serializes just fine, but it is kind of an ugly solution since I need to have a special case for it (and any other iterator methods I might add). My guess is that this has to do with the IEnumerable not being enumerated.
Can I get Json.Net to serialize the result of my iterator functions or will I always need a special case like this? Let me know if any more information or source code is needed and I will post it.
More Info: I am using the .Net framework version 4.0 and I am using Json.Net version 5.0r2
Abridged Source Code of the Iterator Method
public IEnumerable<dynamic> FunctionName()
{
var methodList = typeof(Targets).GetMethods();
foreach (var m in methodList)
{
dynamic info = new ExpandoObject();
info.Name = m.Name;
info.Parameters = from param in m.GetParameters()
select param.Name;
yield return info;
}
}
Source Code of Method Call
...
object ret = null;
if (q == "FunctionName")
{
ret = FunctionName(); // This causes an exception to be thrown later
// ret = FunctionName().ToList(); // This does NOT throw an exception later
}
else
{
ret = DoOtherStuff(q, request);
}
// Serialize the result to JSON
// This line throws the exception
string jsonEncoded = JsonConvert.SerializeObject(ret, Formatting.Indented);
...