Welcome to My WordPress Blog
In C# 3.5, We can create anonymous types to improve our efficiency, usually we do it like this:
var coords = new { X=1.5f, Y=2.0f };
Console.WriteLine( coords.X );
coords.X = 1.0f;
Using anonymous types, we do not need to define classes one by one. And even, we can combine several anonymous type values to one new value:
var coords = new { X=1.5f, Y=2.0f };
var point = new { Coord = coords, Color = "Red" };
It’s easy to use to keep temporary values or create new value in linq expressions, but, as anonymous type is internal, we cannot return anonymous type value from methods, the following code is invalid:
static object ReturnAnonymousTypeValue()
{
return new { X = 1.5f, Y = 2.0f };
}
static void ReadAnonymousTypeValueFromAntherMethod()
{
var val = ReturnAnonymousTypeValue();
Console.WriteLine(val.X); //Invalid
}
(In C# 4.0, we can use “dynamic” to reach the goal.)
In method ReturnAnonymousTypeValue, as the returnd value has no type name, the returnd type is object. also we can not cast the object value to “some type” in the same reason. We lose the data… No solution to solve it. There are too many limits of anonymous types.
Now, I have a requirement of getting data from WCF but I do not want to create class(Too tedious and inflexible), and I want to do it like this:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(...)]
public class Task
{
[OperationContract]
[WebInvoke(...)]
public object Test(bool s)
{
return new { Enabled = s, Name = "Test" };
}
}
Then get the data using ajax:
$.ajax({
url: 'Task.svc/Test',
data: '{"s":true}',
type: 'post',
dataType: 'json',
contentType: 'text/json',
success: function(data) { alert( $.toJSON( data.d ) ); }
});
It obviously cannot work, when invoke the method, exception throws, because DataContractSerializer cannot Serialize anonymous types(also class with no attribute “DataContract”).
We can only code like this:
[ServiceContract(Namespace = "")][AspNetCompatibilityRequirements(...)]
public class Task{
[OperationContract]
[WebInvoke(...)]
public TestType Test(bool s)
{
return new TestType { Enabled = s, Name = "Test" };
}
}
[DataContract]
public class TestType{
[DataMember]
bool Enabled{ get; set; }
[DataMember]
string Name{ get; set; }
}
Can C# return anonymous types from methods? NO! It cannot in any case, not to mention WCF need serialize the value.
So, we should look for other ways.
In general, if we want to serialize one valuable, the type of the val should take the attributes [Serializable] or [DataContract] or other relateds, or implement the interface ISerializable. Anonymous types cannot reach the goal.
But there is one special class in .Net Framework “JavaScriptSerializer” in System.Web.Script.Serialization,System.Web.Extensions.dll, which can serialize any types to json format string!
public static class JsonSerialization
{
public static string ToJson(this object data)
{
return new JavaScriptSerializer().Serialize(data);
}
}
Modify the WCF:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(...)]
public class Task
{
[OperationContract]
[WebInvoke(...)]
public string Test(bool s)
{
return new { Enabled = true, Name = "Test" }.ToJson();
}
}
The method Test returns one string with json format and you can serialize anything and return it!
In browser, change the success callback:
success: function(data) { var jd = $.evalJSON( data.d ); alert(jd.Enabled); }
As data.d is the return string with json format, Just get json value from data.d using $.evalJSON.
Look! Isn’t it elegent? We can return any data easily with no complex class definition.
Download:
Reference:
- JavaScriptSerializer
- Jquery Json PlugIn