Using StringWriter for XML Serialization Using StringWriter for XML Serialization xml xml

Using StringWriter for XML Serialization


One problem with StringWriter is that by default it doesn't let you set the encoding which it advertises - so you can end up with an XML document advertising its encoding as UTF-16, which means you need to encode it as UTF-16 if you write it to a file. I have a small class to help with that though:

public sealed class StringWriterWithEncoding : StringWriter{    public override Encoding Encoding { get; }    public StringWriterWithEncoding (Encoding encoding)    {        Encoding = encoding;    }    }

Or if you only need UTF-8 (which is all I often need):

public sealed class Utf8StringWriter : StringWriter{    public override Encoding Encoding => Encoding.UTF8;}

As for why you couldn't save your XML to the database - you'll have to give us more details about what happened when you tried, if you want us to be able to diagnose/fix it.


When serialising an XML document to a .NET string, the encoding must be set to UTF-16. Strings are stored as UTF-16 internally, so this is the only encoding that makes sense. If you want to store data in a different encoding, you use a byte array instead.

SQL Server works on a similar principle; any string passed into an xml column must be encoded as UTF-16. SQL Server will reject any string where the XML declaration does not specify UTF-16. If the XML declaration is not present, then the XML standard requires that it default to UTF-8, so SQL Server will reject that as well.

Bearing this in mind, here are some utility methods for doing the conversion.

public static string Serialize<T>(T value) {    if(value == null) {        return null;    }    XmlSerializer serializer = new XmlSerializer(typeof(T));    XmlWriterSettings settings = new XmlWriterSettings()    {        Encoding = new UnicodeEncoding(false, false), // no BOM in a .NET string        Indent = false,        OmitXmlDeclaration = false    };    using(StringWriter textWriter = new StringWriter()) {        using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {            serializer.Serialize(xmlWriter, value);        }        return textWriter.ToString();    }}public static T Deserialize<T>(string xml) {    if(string.IsNullOrEmpty(xml)) {        return default(T);    }    XmlSerializer serializer = new XmlSerializer(typeof(T));    XmlReaderSettings settings = new XmlReaderSettings();    // No settings need modifying here    using(StringReader textReader = new StringReader(xml)) {        using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) {            return (T) serializer.Deserialize(xmlReader);        }    }}


First of all, beware of finding old examples. You've found one that uses XmlTextWriter, which is deprecated as of .NET 2.0. XmlWriter.Create should be used instead.

Here's an example of serializing an object into an XML column:

public void SerializeToXmlColumn(object obj){    using (var outputStream = new MemoryStream())    {        using (var writer = XmlWriter.Create(outputStream))        {            var serializer = new XmlSerializer(obj.GetType());            serializer.Serialize(writer, obj);        }        outputStream.Position = 0;        using (var conn = new SqlConnection(Settings.Default.ConnectionString))        {            conn.Open();            const string INSERT_COMMAND = @"INSERT INTO XmlStore (Data) VALUES (@Data)";            using (var cmd = new SqlCommand(INSERT_COMMAND, conn))            {                using (var reader = XmlReader.Create(outputStream))                {                    var xml = new SqlXml(reader);                    cmd.Parameters.Clear();                    cmd.Parameters.AddWithValue("@Data", xml);                    cmd.ExecuteNonQuery();                }            }        }    }}