如何解析 ODATA 错误

How To Parse ODATA Error

<?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

我有一个从 WEB API 2 ODATA 源返回的 XML 结构。我需要在服务器上解析此错误,然后将一个新错误传递给 client.I 已尝试将其反序列化为各种异常类型,但 Exception Implement IDICTIONARY 阻止了这一点。如何将其反序列化为强类型对象?

如果上面的问题不容易解决,我想我的另一个问题是what is best practice for handling these errors

关于如何处理您收到的这些错误消息,我的建议是创建一个外观相似的 class 结构,而不是尝试将信息序列化到 Exception 对象中。

这为您提供了更多的灵活性,以防您的 XML 源决定更改其错误消息的结构,而不是基于异常的结构,此外,它还删除了尝试找出如何反序列化 Exception 对象的要求(根据一些搜索,这有点复杂)。

所以使用Visual Studio中的工具将XML文本转换成C#classes(在Edit下找到=>Paste Special => Paste XML as 类),得到下面的class结构
实际结构是根据该工具生成的内容修改的,因为它喜欢使 classes 膨胀很多。

[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; }
}

利用这个 class 结构,您可以轻松地将收到的 XML 反序列化为强类型对象,并以您喜欢的任何方式进一步使用它。

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
  }
}

您现在还可以自由地为变量提供任何更能描述 yourself/your 团队的名称,并使用 XmlElement 属性将您的属性 link 设置为内部的实际名称XML.

关于使异常可序列化,还有一个非常有趣和好的 Q/A,我也推荐阅读:
What is the correct way to make a custom .NET Exception serializable?