Friday, September 21, 2012

WCF Ria Services overcoming limitations on "Return Types”

I’m a fan of WCF Ria Services,  however it sometimes have strange limitations whose motivations doens’t appears obvious. One of them I believe it’s the limitation on types that a DomainServices can returns.
If you try to return for example a IEnumerable<IList<string>> you’ll get a message like that
Operation named 'MyOperation' does not conform to the required signature. Return types must be an entity or complex type, a collection of entities or complex types, or one of the predefined serializable types.
A simple way to overcome this limitation is to “pre-serialize” your object. I use a couple of methods to serialize/deserialize both client and server side
public static class Serialization
    {
        public static string Serialize<T>(T obj)
        {
            var ms = new MemoryStream();
            var ser = new DataContractSerializer(typeof (T));
            ser.WriteObject(ms, obj);
            byte[] array = ms.ToArray();
            ms.Close();
            return Encoding.UTF8.GetString(array, 0, array.Length);
        }

        public static T Deserialize<T>(string obj) where T : class
        {
            if (obj == null)
                return null;
            var serializer = new DataContractSerializer(typeof (T));
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(obj));
            var result = serializer.ReadObject(stream) as T;
            return result;
        }
    }


So, Server side I use something like
[Invoke]
public IEnumerable<string> MyOperation()
{
    List<string> list1 = new List<string>(){"ciao", "a" , "tutti"};
    List<string> list2 = new List<string>(){"hello", "world"};
    List<string> listOfSerializedList = new List<string>();
    listOfSerializedList.Add(Serialize(list1));
    listOfSerializedList.Add(Serialize(list2));
    return listOfSerializedList;
}


while client side
var myOperationResult = myDomainContext.MyOperation();
List<List<string>> myRealResult = new List<List<string>> ();
foreach (var myList in myOperationResult )
{
    myRealResult.Add(Deserialize<List<string>>(myList));
}
Of  course the code is just a proof of concept, and it’s better to package it in more “productive” methods but it should get the idea behind it.
Hope this helps


No comments: