2

I have a pretty large LINQ query which reads XML nodes into object properties, however a line in my query is causing a System.FormatException exception based on "Input string not in a correct format".

DeliveryFee = x.Descendants("LineItemShipping").Select(e => (double)e.Element("TotalPrice")).FirstOrDefault(),

(double)e.Element("TotalPrice") // this text in the line is highlighted by the debugger so this element must be the cause

There is 1000's of records in the XML document so I am having trouble locating the record causing the exception, is there a way I can "throw" the value causing the error to a catch() statement? I'm not exactly sure how to debug a LINQ query to get the value at runtime and I'm sure it's just an issue where that XML node is empty for this specific record. (or contains an illegal character)

I know it's a specific record as I can pull many rows without an issue however when I try to pull a specific subset that's when I get the exception, so I know it is localized to a months worth of data but I am unable to narrow it down more.

Aaron McKelvie
  • 167
  • 4
  • 17

3 Answers3

2

To find this bug, first enable breaking when an exception is thrown in visual studio, via Debug -> Exceptions. Either enable breaking on all exceptions, or enable breaking on System.FormatException.

Now Visual Studio will stop when an exception is thrown for a LineItemShippingnode with an invalid TotalPrice. Then, in the immediate window, you can use the AncestorsAndSelf() method to find the problematic node by typing:

e.Element("SomeStatus").AncestorsAndSelf().ToArray()

Visual Studio will show you the path of XElement's that generate the exception. This should allow you to find the problematic XML node.

dbc
  • 104,963
  • 20
  • 228
  • 340
1

You can add a try catch statement to the select expression, something like this:

    var DeliveryFee = x.Descendants("LineItemShipping").
        Select(e => {
            try
            {
                var item = (double)e.Element("TotalPrice");  
                return item;
            }
            catch(Exception ex)
            {
                //This is just so it will compile and have a return value                        
                return double.MinValue;
            }                  
        }).
        FirstOrDefault();
Y.S
  • 1,860
  • 3
  • 17
  • 30
0

Try changing (double) to (double?) to handle empty cases and a ?? 0 to convert nulls to zero:

(double)(x.Descendants("LineItemShipping")
          .Select(e => (double?)e.Element("TotalPrice")).FirstOrDefault()) 
          ?? 0)
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69