In theory XML should always be portable between different versions of .NET Framework/.NET Core/.NET. But there are always exceptions to the rule.
For example IF you're moving System.Data.DataTable
s around in XML format, and IF some of those data tables contain columns of type System.Guid
, then you're likely in for a surprise! Consider the following example code:
using System;
using System.Data;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
public class Program
{
internal static string SerializeToXml<T>(T input)
{
var writerSettings = new XmlWriterSettings()
{
Encoding = new UTF8Encoding(false),
Indent = true
};
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream, writerSettings))
{
(new XmlSerializer(typeof(T))).Serialize(writer, input);
return Encoding.UTF8.GetString(stream.ToArray());
}
}
public static void Main()
{
var dt = new DataTable("Name");
dt.Columns.Add("Example", typeof(Guid));
Console.WriteLine(SerializeToXml(dt));
}
}
Unlike most other system types System.Guid
gets a version-specific msdata:DataType
attribute included in the column definition and that will throw a System.InvalidOperationException: There is an error in XML document (.., ...)
wrapping a System.ArgumentException: Column requires a valid DataType
when an incompatible runtime attempts to deserialize it.
.NET Framework 4.7.2 output:
<?xml version="1.0" encoding="utf-8"?>
<DataTable>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Name" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="Example" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataTable>
.NET Core 3.1 output: (yes, it outputs version 4.0.0.0)
<?xml version="1.0" encoding="utf-8"?>
<DataTable>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Name" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="Example" msdata:DataType="System.Guid, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataTable>
.NET 5 output:
.NET 5
<?xml version="1.0" encoding="utf-8"?>
<DataTable>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Name" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="Example" msdata:DataType="System.Guid, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataTable>
.NET 6 output:
<?xml version="1.0" encoding="utf-8"?>
<DataTable>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Name" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="Example" msdata:DataType="System.Guid, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataTable>
.NET 7 output:
<?xml version="1.0" encoding="utf-8"?>
<DataTable>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Name" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="Example" msdata:DataType="System.Guid, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataTable>