Nice of you to drop by the sitelett and you're welcome to anything you find but realize that these pages are just a collection of tips, tricks and thoughts that I don't want to forget and yet don't really have the brainspace to keep remembering day in and day out. All I have to do is remember where I put something, not exactly what it is, to get reuse out of it. You may find a lot of things that are obvious, but I'll bet not one thing you'll find is anything that you knew the day you were born.
Anyway, here's the start of a few from my current summer vacation...
ValueAsWhoops
You're iterating through an XML document, your empty Date/Time type element values passed right through schema validation because you made them optional. Now you pass the XML into a manual XPath-based deserializer and because you made the related DateTime member Nullable you can just relax and trust the XPathNodeIterator's Current.SelectSingleNode to handle everything. Right?
Yeah, I thought so too, but fact is doing extra lines of protection code beats all of the ValueAs options, because the following will blow up on an empty orderDate element:
...
XPathNodeIterator it = navigator.Select("purchaseOrder");
while (it.MoveNext())
{
if (it.Current.SelectSingleNode("orderDate") != null)
{
PutOrderDate(it.Current.SelectSingleNode("orderDate").ValueAsDateTime;
}
}
...
Eghads the basics. Your custom gatekeeper method PutOrderDate can take a Nullable DateTime, the node isn't null, but the value in the element is and the ValueAsDateTime property dies on it. Use the following route instead:
...
XPathNodeIterator it = navigator.Select("purchaseOrder");
string temp;
DateTime dtTemp;
while (it.MoveNext())
{
if (it.Current.SelectSingleNode("orderDate") != null)
{
temp = it.Current.SelectSingleNode("orderDate").Value;
if (DateTime.TryParse(temp, out dtTemp))
{
PutOrderDate(dtTemp);
}
else
{
PutOrderDate(null);
}
}
...
Likewise when you're tempted to use ValueAsInt, ValueAsBool and so on, even with internal "trusted" docs it's best to to the tryparse to a temporary variable instead. Yeah, it's overhead and yeah it's extra lines but expect a decimal and get a file with a string and the overhead is appreciated.
added June 2006
UTF WTF
Ok, this came up a long while back and at that time it took me a lot of minutes to get to the bottom of it. And I was so proud ;-).
The other night when rechecking something I'd already called complete I noticed that I'd gone down the wrong path again, and so I figured I'd force my next recollection by having shared it with you.
If you've not yet had the opportunity to do Object to XML conversion for more than inter-app serialization as in for exporting the XML strings for external use, trust me, you will. And when that happens I hope this heads up will help you out.
Serializing to XML is really easy and you can find lots of examples of it all over the place. But what the heck I'll give you another one right here. Take this easy Person object:
class Person
{
#region declarations
private string _firstName = "";
private string _lastName = "";
private int _numberOfToes = 0;
#endregion
#region public props
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public int NumberOfToes
{
get { return _numberOfToes; }
set { _numberOfToes = value; }
}
#endregion
}
And now add in the typical XML Serialization.
Hang on a sec... by typical we mean "typical *Custom* serialization" because while using the XMLSerializer can be great for some XML and with .Net2 it has lot of new attributes that give it more fine-grained control it still has that glaring limitation of all serializeable properties being required to be fully read/write - naked to the world. That can get in the way fast of making a nice object interface for devs who don't want to and shouldn't have to think about the persistence mechanism of the objects they're using. (Want a great example of the multitude of problems you can get in with the “easy” XMLSerializer? Just take a look at the last couple of Rockford Lhotka books, he’s trying to smash at his objects with that sledgehammer until they bend to his will but unfortunately it just ain’t the way to go yet with the types of XML B2B structures, and worse he’s telling a lot of other developers to blindly pick up hammers and waste time banging away till their foundations are brittle.)
Anyway, I digress. Here's a traditional Custom serialization style for the Person class above:
using System;
using System.Text;
using System.Xml;
using System.IO;
namespace XMLUTFDemo
{
class Person
{
...
#endregion
#region serialization
public string GetXML()
{
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
settings.NewLineOnAttributes = true;
settings.Encoding = Encoding.UTF8;
settings.ConformanceLevel = ConformanceLevel.Document;
XmlWriter w = XmlWriter.Create(sb, settings);
GetXML(w);
w.Close();
return sb.ToString();
}
public void GetXML(XmlWriter w)
{
w.WriteStartElement("myPerson");
//explicit string style
w.WriteStartElement("firstName");
w.WriteString(_firstName);
w.WriteEndElement();
//shorthand string style
w.WriteElementString("lastName", _lastName);
//non-string example
w.WriteStartElement("toeNumber");
w.WriteValue(_numberOfToes);
w.WriteEndElement();
w.WriteEndElement();
w.Flush();
}
#endregion
}
}
Great. A dev-user will create a Person instance, then get the XML string by calling the GetXML() method, which will set up the writer with the format for the resulting document and pass the writer to code that will slip in the content. This overloading style is typical because it allows complex object graphs to have the root level object just pass its writer object into the child GetXML(XMLWriter w) method and build the well-formed Document out of fragments.
Here's the problem with it though... the StringBuilder. Once you stick text in a StringBuilder it's gone Unicode, and Unicode it stays. In XML rule of thumb parlance that means UTF-16 encoding. That means that your target better be ready for Unicode strings and if they aren't then parser go boom - or “BOM” to be specific because the root of the issue is the Byte Order Mark, the little invisible instruction at the header of the text file that tells the renderer what it’s supposed to render.
(FYI on the obvious: The XML declaration saying “utf-16” isn’t the issue, you can take the declaration out or manually rewrite it and it’s still the same encoding because encoding, and the creation of the BOM - is determined by the system that originally wrote the file).
But doesn’t that one little line ---
settings.Encoding = Encoding.UTF8;
--- take care of it? Nope. That line is ignored if the bucket you're putting the strings in is Unicode, the Writer Settings thank you for your typing and won't condescend to tell you that they're smarter than you and will just ignore your wishes.
Proof:
With the above class in a WinForm project, add a button to the form and stick this in the stub:
private void butWithSB_Click(object sender, EventArgs e)
{
Person p = new Person();
p.FirstName = "Jeremy";
p.LastName = "Patil";
p.NumberOfToes = 10;
MessageBox.Show(p.GetXML());
System.IO.File.WriteAllText(DEMO_XML_PATH, p.GetXML());
}
Run & click and look closely at that XML declaration.

UTF-16. Fine for the dialog and fine to pour into another .Net based object’s custom LoadXML method, but not so fine with a parser that doesn't understand Unicode... such as trying to open the file in IE.

The deal?
Go a little lower, lose a little intuitiveness for the sake of more control, and use streams.
Change the above GetXML() setup method as follows:
public string GetXML()
{
string retVal = "";
using (MemoryStream ms = new MemoryStream())
{
StreamWriter sw = new StreamWriter(ms);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = new String(' ', 4);
settings.NewLineOnAttributes = true;
settings.Encoding = Encoding.UTF8;
settings.ConformanceLevel = ConformanceLevel.Document;
XmlWriter w = XmlWriter.Create(sw, settings);
GetXML(w);
w.Close();
using (StreamReader sr = new StreamReader(ms))
{
ms.Position = 0;
retVal = sr.ReadToEnd();
sr.Close();
}
return retVal;
}
}
... gives you the UTF-8 that you need.


Hope that helps.
Robert Smith
Kirkland, WA
added November 2006