For the love of all things holy, how do you distinguish between different "exception flavors" within the predefined .NET exception classes?
For example, a piece of code might throw an XmlException
under the following conditions:
- The root element of the document is NULL
- Invalid chars are in the document
- The document is too long
All of these are thrown as XmlException
objects and all of the internal "tell me more about this exception" fields (such as Exception.HResult
, Exception.Data
, etc.) are usually empty or null.
That leaves Exception.Message
as the only thing that allows you to distinguish among these exception types, and you can't really depend on it because, you guessed it, the Exception.Message
string is glocabilized, and can change when the culture changes. At least that's my read on the documentation.
Exception.HResult
and Exception.Data
are widely ignored across the .NET libraries. They are the red-headed stepchildren of the world's .NET error-handling code. And even assuming they weren't, the HRESULT
type is still the worst, downright nastiest error code in the history of error codes. Why we are still looking at HRESULTs in 2010 is beyond me. I mean if you're doing Interop or P/Invoke that's one thing but... HRESULTs have no place in System.Exception. HRESULTs are a wart on the proboscis of System.Exception.
But seriously, it means I have to set up a lot of detailed specific error-handling code in order to figure out the same information that should have been passed as part of the exception data. Exceptions are useless if they force you to work like this. What am I doing wrong?
EDIT. A DAY LATER.
Thanks for all the comments and responses. I'm learning a general lesson here ("error messages suck") even if I haven't quite solved the specific problem. Here's the specific scenario I'm deaing with.
Our application consumes XML files produced by a third party. These XML files sometimes contain illegal characters that really have no business being in an XML file. These illegal chars cause a (validating) XmlReader to blow up with an "illegal char on line X" exception". We have to process these files, however; we can't simply tell the user, "sorry, that file doesn't conform to the official XML spec." Our users don't even really know what XML is.
Microsoft has an official (and quite strange to me) recommendation in this case (the case where an XML document contains illegal characters): to load the file into a stream, iterate to the specific line containing the error (as provided, ironically, in the XmlException object), and to custom-replace the offending char with a legal one. Then try loading the doc into the validating XmlReader again, and seeing if it blows up. Here's the Knowledge Base article describing the technique.
So fine, we're doing that, and it works well enough. The problem is that sometimes these XML files we get are malformed in other ways: they might be empty, they might be missing a closing tag, etc. So if you follow the MS recommendation, you're actually hooking your "replace illegal chars" logic into the catch block where you catch the original exception thrown by the validating reader.
That's fine if the exception is in fact an "illegal char" exception. But if it's a "root element missing" or "missing closing tag" exception, you find that the MS technique to go in and replace the offending char itself blows up, because not only is there not an offending char, there are no chars at all, or there are, but they're invalidly-formed XML, or whatever. At this point you're in a doubly-nested catch-inside-a-catch, your hair's turning gray and falling out, your eyes are crimson red with caffeine fatigue, and you're questioning the sanity, let alone the utility, of using validating readers against real-world XML.
So what I need is a way of telling, in that initial catch(XmlException) block, whether this is a "root element missing" or a "invalid char" exception, so I can take the appropriate action. One thing we can't do is prevent our users to open a document that contains a few invalid chars. We have to process those documents regardless, and I guess it's looking like the only solution is to iterate through every char in the document ahead of time, viewing it as a text stream rather than as XML, find the illegal chars, replace them, then load the thing with the validating XmlReader and if it blows up, we know it's not an illegal char exception, because we stripped illegal chars beforehand.
Before doing that I thought I'd at least ask 1) can we get better information out of the XmlException object and I was hoping somebody would tell me 2) "it's okay to key off the XmlException.Message string. They say it's localized but it's not really. This string will be the same across all versions and cultures of Windows."
But nobody has told me that.