22

.NET's Deserilization errors are quite generic, for example something like this:

System.ArgumentException: Object of type 'System.Uri' cannot be converted to type 'System.String'.

It's clear that we changed the type of a property in an object but there are like 10-15 different classes in this serialized object, so it's really hard to figure out which one we changed or which commit messed this up.

Is there anyway to get information about which property in which class (or at least in which class) actually causing this error? Is there any external tool or known ways to do this?

P.S. Before anyone start telling me why I shouldn't use binary serializer or why I should X,Y instead etc. for backward compatibility, please save the advice on those. I'm aware of all those but that's not the question.

dr. evil
  • 26,944
  • 33
  • 131
  • 201
  • 4
    did you see InnerException if you dont have more info? – DesignFirst Feb 03 '11 at 13:42
  • 10-15 doesn't sound a huge number for debugging purposes; I don't know an easy way to debug that off-hand – Marc Gravell Feb 03 '11 at 13:44
  • @Marc Gravell: I think that @dr. evil means that the instance being deserialized has references to 10-15 other distinct classes, all of which (including the root) can have `N` properties (even with one class, you have `N` properties) which is indeterminate, so that can potentially be a large number of properties to wade through. – casperOne Feb 03 '11 at 13:57
  • 1
    @casperOne yes, I'm painfully aware of the joys of trying to locate serialization bugs ;p – Marc Gravell Feb 03 '11 at 13:59
  • @DesignFirst InnerException is `Nothing` – dr. evil Feb 03 '11 at 14:07
  • Marc to be honest I don't even know how much. You know how serilization gets out of hand *very* quickly :) – dr. evil Feb 03 '11 at 14:29
  • Can you try Serialising/Deserialising any of the referenced classes on their own? – Kernow Steve Feb 03 '11 at 16:13
  • @Kernow I cannot as the data I try to deserialize is stored with a previous version hence I'm getting the error. Theoretically I can obviously by using the old version and re-compiling etc. etc. but it would take ages hence defeats the purpose of the question :) – dr. evil Feb 03 '11 at 16:54
  • It's things like this that make me wish there was a DTrace for .Net. –  Feb 03 '11 at 18:23
  • If you have the previous source code, a file difference tool such as WinMerge may help to find the relevant changes. – Kernow Steve Feb 04 '11 at 09:25

3 Answers3

10

If you enable debugging into framework code (see this link) and then press ctrl + shift + e and select all managed code exceptions the error will appear in the actual source line that fails. You should be able to use the stack trace then to find out what part of the object it was trying to deserialize at that point.

It's not easy, but that's how we ended up doing it.

Matthew Steeples
  • 7,858
  • 4
  • 34
  • 49
1

Looking at the Inner Stack trace can be useful. The serializer generates a class specifically to handle the type you are wanting to serialize/deserialize.

Just by looking at the function names of the functions involved in the stacktrace you can track down which node node is breaking.

This helps narrowing down where the problem may lie, especially with large complex XML files.

Example:

  at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Xml.XmlConvert.ToInt32(String s)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderXML.Read13_Item(Boolean isNullable, Boolean checkType) //Tells you the issue is on the RootNodeSubNodeSubSubNode on an item withing it.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderXML.Read17_RootNodeSubNodeSubSubNode(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderXML.Read26_RootNodeSubNode(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderXML.Read50_RootNode(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderXML.Read51_RootNode()
Oliver
  • 35,233
  • 12
  • 66
  • 78
  • 2
    how to know which attribute it was accessing. I am getting The Input string was not in correct format. I have big xml file which has many attributes. I want to know which one caused the problem – Ziggler Apr 07 '15 at 23:09
1

There's a couple of different things you can do, none of them great. Especially with binary serialization. You could add custom serialization handling with the ISerializable interface, which would allow you to step through the deserialization process in the debugger.

Have you considered switching to Xml serialization for development/debugging purposes? There's a few more hooks that you can use with Xml serialization. But it sounds like that won't work for you, as you're probably dealing with either a remote interface or older binary data stored on disk that you need to read.

But even easier would be to look through your source control system's logs for the method with the changed type.

MonkeyWrench
  • 1,809
  • 2
  • 24
  • 48
  • We are currently in the process of checking previous version to fix the problem, however I was hoping to find maybe a clever tool to help me. Maybe when I give it my DLLs it can deserilize and visualise the object. Too optimistic, eh? :) – dr. evil Feb 03 '11 at 21:31
  • Yeah, there's many places where the .Net exceptions contain little or no info. Real shame. The Configuration classes also throw some very cryptic exception messages when you have custom classes. At least you know its a type change, which gives you a good head start. – MonkeyWrench Feb 03 '11 at 23:18