Description
Description
The WCF binary XML format written by XmlDictionaryWriter.CreateBinaryWriter
allows for a binary representation of DateTime
objects that is shorter and faster to deserialize than the standard string presentation, e.g. 2021-01-01T00:00:00. The .NET Framework implementation uses the binary format everywhere except in XML attributes. The .NET Core implementation, on the other hand, uses it when serializing DateTime
arrays (DataTime[]
), but not for lists or object members, e.g. List<DateTime>
. That leads to much larger blobs when the serialized objects contain many DateTime
s and, more importantly, significantly longer deserialization times.
Reproduction Steps
The following unit test that can be added to src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs demonstrates the issue by binary-serializing a single DateTime
object.
[Fact]
public static void DCS_BinarySerializationOfDateTime()
{
DateTime dateTime = DateTime.Parse("2021-01-01");
MemoryStream ms = new();
DataContractSerializer dcs = new(dateTime.GetType());
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(ms, null, null, ownsStream: true))
dcs.WriteObject(writer, dateTime);
var serializedBytes = ms.ToArray();
Assert.Equal(72, serializedBytes.Length);
}
Expected behavior
The binary serialization should be 72 bytes long, matching .NET Framework 4.8, and the above unit test should pass.
Actual behavior
The binary serialization is 84 bytes long, using the textual representation of DateTime
, and the unit test fails.
Regression?
Yes, this works in .NET Framework 4.7.2 and 4.8. Probably earlier versions as well.
The bug has been presented in all versions of .NET Core as far as I can tell.
Known Workarounds
No response
Configuration
Confirmed in .NET Core 3.1 and .NET 5.0 on x64 Windows. By code inspection the same issue is present in .NET 6.0 and also versions before 3.1. As far as I can tell, the issue is not specific to these configurations.
Other information
The bug has been presented in all versions of .NET Core as far as I can tell. The initial import in the "runtime" git repo has the defect. I traced it to a difference in the implementation of writeDateTime(DateTime value)
in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlWriterDelegator.cs. The .NET Core version is
internal virtual void WriteDateTime(DateTime value)
{
WriteString(XmlConvert.ToString(value, XmlDateTimeSerializationMode.RoundtripKind));
}
which forces the use of the textual DateTime
representation. The .NET Framework sources have
internal virtual void WriteDateTime(DateTime value)
{
writer.WriteValue(value);
}
which delegate to the inner writer object which will use the binary representation in most cases.