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


Wednesday, September 12, 2012

Auto increment build number msbuild 4



If you just need to increment that number in the AssemblyVersion, it’s amazingly easy:
[assembly: AssemblyVersion("1.0.*")]


However the above  will increment only the AssemblyVersion (as a note: the third number represent the number of days since 1/1/2000 and the third HHmm of your local time) if  you rather want to increment the AssemblyFileVersion things complicate a bit… as someone suggest on stackoverflow you can omit the AssemblyFileVersion in your AssemblyInfo.cs and you’ll get the operating system displaying as FileVersion the value of AssemblyVersion.


I, however, was looking for something different. I wanted the FileVersion to auto increment at each build accordingly to my day’s fantasies.


I’ve discovered from the msbuild master Sayed Ibrahim that in msbuild 4.0 ther’s a new feature called Inline Task. It’s just like a regular msbuild custom task, but it’s defined inline within the project file. And that's a great news.


So I created an inline task like this


<UsingTask
    TaskName="SetVersion"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
    <ParameterGroup>
      <FileName ParameterType="System.String" Required="true" />
      <MajorVersion ParameterType="System.Int32" Required="true" />
      <MinorVersion ParameterType="System.Int32" Required="true" />
    </ParameterGroup>
    <Task>
      <!--<Reference Include=""/>-->
      <Using Namespace="System"/>
      <Using Namespace="System.IO"/>
      <Code Type="Fragment" Language="cs">
        <![CDATA[
            string dayCount = Math.Floor(DateTime.Now.Subtract(new DateTime(1979,5,2)).TotalDays).ToString();
            string text = String.Format("[assembly:System.Reflection.AssemblyFileVersion(\"{0}.{1}.{2}.{3}\")]", MajorVersion, MinorVersion, dayCount, DateTime.Now.ToString("HHmm") );
            File.WriteAllText(FileName, text);
            return true;
  ]]></Code>
    </Task>
  </UsingTask>


and called it in “BeforeBuild” Target


<Target Name="BeforeBuild">
    <SetVersion FileName="$(MSBuildProjectDirectory)\Properties\VersionInfo.cs" MajorVersion="1" MinorVersion="3" />
</Target>


The file “Properties\VersionInfo.cs” is an empty file included in my project, that my InlineTask code fills.


Of course there are other ways to do the same thing with AutoBuildVersion being one of the easiest, but this one is customizable by code and  don’t have dependencies so it compile fine everywhere .net 4 is installed.


Marco Casamento