Daily Archives: 2014/12/09

XmlSerializer bug in .NET4.5 and legacy serializer

Starting with .NET4.5 (which is an in-place update of .NET4) Microsoft created a completely new XmlSerializer. And as a developer you know, that it is almost impossible to re-write a software and match the whole features of the original software.
But Microsoft was sure, that the new implementation is not only faster, but will also replace the old XmlSerializer for almost all cases… that was the reason why Microsoft are using the new implementation by default. This is even true, if you only have shipped your app with .NET4 and a different program installs the .NET4.5 update on the computer… then your old programm will also use the new XmlSerializer…

And my (simple) program fails in that case! If I want to serialize an object, if throws and System.InvalidProgramException exception ;(

using System.ComponentModel;
using System.IO;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
  public class Program
  {
    static void Main()
    {
      new XmlSerializer(typeof (Program)).Serialize(new StringWriter(), new Program());
    }

    [DefaultValue(0.0)]
    public decimal Value;
  }
}

What is now the problem? For me it seems very normal… The problem is, that I used a “DefaultValue”, which is a “double” and a field which is a “decimal”. With the old XmlSerializer this was no problem… internally the conversion was done correctly. But it seems that the new one, now tries to assign the double to the decimal and fails

Now there are two possibilities to solve this problem:

  1. Replace “0.0” with “0” which leads to an interger (int) and this can be assigned to a decimal
  2. Enable the old bahavior again 😉

Microsoft also knew about the impossibility to replace an old component with a new one, which exactly the same behavior 😉 Therefor you can enable the old XmlSerializer via app.config:

<configuration>
  <system.xml.serialization>
    <xmlSerializer useLegacySerializerGeneration="true"/>
  </system.xml.serialization>
</configuration>

But there is a big warning in the knowledgebase article: “We do not recommend that you apply this workaround on a computer that is running a version of the .Net framework that is earlier than the .Net framework 4.5.”

So if you want to ship your application with the old behavior and you are not sure that .NET4.5 is installed, then you should use the following app.config entry, which works in .NET4 and 4.5 😉

<configuration>
  <appSettings> 
    <add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
  </appSettings>
</configuration>

Of course, I have choosen the first optional and have replaced “DefaultValue(0.0)” with “DefaultValue(0)”. Lukily, we had no decimal places 😉