1
<?xml version="1.0" encoding="utf-8"?>
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <m:code />
    <m:message xml:lang="en-US">An error occurred while processing this request.</m:message>
    <m:innererror>
        <m:message>Exception has been thrown by the target of an invocation.</m:message>
        <m:type>System.Reflection.TargetInvocationException</m:type>
        <m:stacktrace></m:stacktrace>
        <m:internalexception>
            <m:message>An error occurred while executing the command definition. See the inner exception for details.</m:message>
            <m:type>System.Data.Entity.Core.EntityCommandExecutionException</m:type>
            <m:stacktrace></m:stacktrace>
            <m:internalexception>
                <m:message>Cannot insert duplicate key row in object 'XXXX' with unique index 'XXXXXX'. The duplicate key value is (XXXXX)</m:message>
                <m:type>System.Data.SqlClient.SqlException</m:type>
                <m:stacktrace></m:stacktrace>
            </m:internalexception>
        </m:internalexception>
    </m:innererror>
</m:error>" System.Data.Services.Client.DataServiceClientException

I have this XML structure coming back from a WEB API 2 ODATA source. I need to parse this error at the server then pass a new error to the client.I have tried deserializing this to various Exception types, but the fact that Exception Implement IDICTIONARY stops that. How can I deserialize this into a strongly typed object?

If the above isn't easily down, I guess my other question would be what is best practice for handling these errors

gh9
  • 10,169
  • 10
  • 63
  • 96

1 Answers1

2

My suggestion as to how to handle these error messages that you get, is to create a similar looking class structure instead of trying to serialize the information into an Exception object.

This allows for a bit more flexibility on your end, in case the source of your XML decides to change the structure of their error messages instead of basing it on the structure of an Exception, plus it removes the requirement to try and figure out how to deserialize an Exception object (which according to a few searches is a bit more complexer).

So using the tool in Visual Studio to convert XML text into C# classes (found under Edit => Paste Special => Paste XML as Classes), the below class structure is obtained.
The actual structure is modified from what that tool generates, since it likes to bloat the classes a lot.

[XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")]
[XmlRootAttribute(ElementName = "error", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata", IsNullable = false)]
public partial class ODATAException
{
  public string code { get; set; }
  public ODATAErrorMessage message { get; set; }
  public ODATAInternalException innererror { get; set; }
}

[XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")]
public partial class ODATAErrorMessage
{
  [XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/XML/1998/namespace")]
  public string lang { get; set; }

  [XmlTextAttribute()]
  public string Value { get; set; }
}

[XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")]
public partial class ODATAInternalException
{
  public string message { get; set; }
  public string type { get; set; }
  public string stacktrace { get; set; }
  public ODATAInternalException internalexception { get; set; }
}

Utilizing this class structure, you can then easily deserialize the received XML into a strong typed object and use it further in whichever way you like.

using (TextReader sampleTextReader = new StringReader(txtInput.Text)) // Change this whereever you get the XML string from
{
  XmlSerializer sampleXmlSeri = new XmlSerializer(typeof(ODATAException));
  ODATAException newExc = sampleXmlSeri.Deserialize(sampleTextReader) as ODATAException;

  if (newExc != null)
  {
    // Do something with the error
  }
}

You are also now free to give the variables any names that are more descriptive to yourself/your team and use the XmlElement attributes to link your properties to the actual names inside the XML.

There is also a very interesting and good Q/A regarding making an exception serializable, that I would recommend reading as well:
What is the correct way to make a custom .NET Exception serializable?

Community
  • 1
  • 1
Bernd Linde
  • 2,098
  • 2
  • 16
  • 22