The Coolness Of Inheritance
May 8, 2012 Leave a comment
I was writing a simple request/response to a non-WCF web service. The service’s request SOAP looked like this:
<?xml version="1.0" encoding="utf-8" ?> <WorkItem AppName='TBD'> <UserName nametype='familiar'>Jamie</UserName> <UserItem>Pencil</UserItem> </WorkItem>
created some classes that matched the request:
[Serializable] public class WorkItem { [XmlAttribute(AttributeName="AppName")] public string ApplicationName { get; set; } [XmlElement] public UserName UserName { get; set; } [XmlElement] public string UserItem { get; set; } }
and
[Serializable] public class UserName { [XmlAttribute(AttributeName = "nameType")] public string NameType { get; set; } [XmlText] public string Value { get; set; } }
I then created a function that populates these classes with the data:
static WorkItem CreateWorkItem() { WorkItem workItem = new WorkItem(); UserName userName = new UserName(); userName.NameType = "familiar"; userName.Value = "Jamie"; workItem.ApplicationName = "TBD"; workItem.UserName = userName; workItem.UserItem = "Pencil"; return workItem; }
Finally, I created a helper function that takes the classes and serializes them as XML:
static XmlDocument CreateXMLDocument(WorkItem workItem) { XmlSerializer serializer = new XmlSerializer(typeof(WorkItem)); XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add(String.Empty, String.Empty); StringWriter stringWriter = new StringWriter(); serializer.Serialize(stringWriter, workItem, namespaces); stringWriter.Close(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(stringWriter.ToString()); return xmlDocument; }
When I run it, things look great… except that the Encoding is wrong:
The path of least resistance would be to set the Encoding property of the StringWriter class. However, that property is read-only. After playing around with the different classes in System.IO that expose encoding (usually though the constructor), I stumbled upon this great article. The easiest way to get UTF-8 encoding in a stringWriter is to override the default implementation in the constructor. I went ahead and created a new class and overrode the Encoding property.
public class UTF8StringWriter : StringWriter { Encoding encoding; public UTF8StringWriter() : base() { this.encoding = Encoding.UTF8; } public override Encoding Encoding { get { return encoding; } } }
Note that I used a local variable. Thank goodness the StringWriter uses its property (not a private variable) in the Serialize method. A big thank you to whoever wrote that class in a proper way. I then changed the stringWriter variable to a UTF8WringWriter like this:
UTF8StringWriter stringWriter = new UTF8StringWriter();