Reputation: 822
I checked this post before but it didn't help me(it doesn't have an accepted answer either).
This test fails:
using System.IO;
using System.Xml.Serialization;
using Xunit;
namespace ATest
{
public class XmlSerializerTest
{
[Fact]
public void DeserializeTest()
{
string request = Serializer.ByteArrayToString(new RegisterRequest{ ... }
.ToXml());
RegisterRequest deserialized = request.DeserializeXmlString<RegisterRequest>();
Assert.NotNull(deserialized);
}
}
public static class Serializer
{
public static T DeserializeXmlString<T>(this string xmlObj)
{
T outputObject;
using (StringReader xmlReader = new StringReader(xmlObj))
{
var serializer = new XmlSerializer(typeof(T));
outputObject = (T)serializer.Deserialize(xmlReader); // throws here
}
return outputObject;
}
public static byte[] ToXml<T>(this T obj)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = false;
using MemoryStream ms = new MemoryStream();
using XmlWriter xmlWriter = XmlWriter.Create(ms, settings);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(String.Empty, String.Empty);
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, namespaces);
return ms.ToArray();
}
// And convert that byte[] to string with this:
public static string ByteArrayToString(byte[] bytes) =>
Encoding.UTF8.GetString(bytes);
}
[XmlRoot(elementName: "RegisterRequest")]
public class RegisterRequest
{
[XmlElement]
public int WorkerId;
[XmlElement]
public string WorkerIP;
[XmlElement]
public int WorkerPort;
}
}
The error I get is:
System.InvalidOperationException: 'There is an error in XML document (1, 1).'
InnerException XmlException: Data at the root level is invalid. Line 1, position 1.
Upvotes: 3
Views: 1993
Reputation: 101493
Problem here is Encoding.UTF8
is UTF-8 encoding with BOM (byte order mark), which means XmlSerializer
emits several bytes at the beginning to indicate said byte order mark. So result of your ToXml
contains those non-character bytes at the beginning, and deserialization fails, because deserialization does not expect them. To fix, tell serializer to not emit BOM by doing this:
XmlWriterSettings settings = new XmlWriterSettings();
//settings.Encoding = Encoding.UTF8;
settings.Encoding = new UTF8Encoding(false); // false means no BOM here
By the way, text you pasted into the question does NOT contain said invisible characters, so with that specific hardcoded string you pasted the problem is not reproducable. However, since you included the code which produced problem string - one can reproduce it by manually calling ByteArrayToString(ToXml(..))
.
Upvotes: 4