0

我在使用 .NET 4.5 WCF 客户端获取 UPS RateWS 服务的肥皂 1.1 故障详细信息元素时遇到问题。

问题是,虽然故障代码和故障字符串元素作为异常的属性.Code恢复正常。.Messagedetail 对象未正确反序列化,并且始终是一个空数组。

我通过从UPS Rating 开发工具包Rates_Pkg_Gnd.zip 文件 SCHEMA-WSDLs 目录中解压缩 wsdl 和 xsds 并在我的文件系统上的 RateWS.wsdl 处指向 Visual Studio 2013s 添加服务参考对话框来生成 WCF 客户端。

实际的接线肥皂故障消息如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header />
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>Client</faultcode>
      <faultstring>An exception has been raised as a result of client data.</faultstring>
      <detail>
        <err:Errors xmlns:err="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1">
          <err:ErrorDetail>
            <err:Severity>Hard</err:Severity>
            <err:PrimaryErrorCode>
              <err:Code>111285</err:Code>
              <err:Description>The postal code 21740 is invalid for AB Canada.</err:Description>
            </err:PrimaryErrorCode>
          </err:ErrorDetail>
        </err:Errors>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

我尝试过捕捉System.ServiceModel.FaultException<UPS.RateService.ErrorDetailType[]>,但 Detail 属性始终是 UPS.RateService.ErrorDetailType[0] 的数组——大小为零。

类似地,捕获 aFaultException并调用.CreateMessageFault()访问会.GetDetail<XmlElement>()产生一个 XML 对象,其中包含一个 ArrayOfErrorDetailType 元素,其中没有任何内容。.GetReaderAtDetailContents()用于获取 XmlReader的替代方法会产生相同的虚假结构。

这是错误消息 xsd:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:error="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1" elementFormDefault="qualified" targetNamespace="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Errors">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element maxOccurs="unbounded" name="ErrorDetail" type="error:ErrorDetailType" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:complexType name="ErrorDetailType">
    <xsd:sequence>
      <xsd:element name="Severity" type="xsd:string" />
      <xsd:element name="PrimaryErrorCode" type="error:CodeType" />
      <xsd:element minOccurs="0" name="MinimumRetrySeconds" type="xsd:string" />
      <xsd:element minOccurs="0" name="Location" type="error:LocationType" />
      <xsd:element minOccurs="0" maxOccurs="unbounded" name="SubErrorCode" type="error:CodeType" />
      <xsd:element minOccurs="0" maxOccurs="unbounded" name="AdditionalInformation" type="error:AdditionalInfoType" />
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="CodeType">
    <xsd:sequence>
      <xsd:element name="Code" type="xsd:string" />
      <xsd:element name="Description" type="xsd:string" />
      <xsd:element minOccurs="0" name="Digest" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="AdditionalInfoType">
    <xsd:sequence>
      <xsd:element name="Type" type="xsd:string" />
      <xsd:element maxOccurs="unbounded" name="Value" type="error:AdditionalCodeDescType" />
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="AdditionalCodeDescType">
    <xsd:sequence>
      <xsd:element name="Code" type="xsd:string" />
      <xsd:element minOccurs="0" name="Description" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="LocationType">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="LocationElementName" type="xsd:string" />
      <xsd:element minOccurs="0" name="XPathOfElement" type="xsd:string" />
      <xsd:element minOccurs="0" name="OriginalValue" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>
4

3 回答 3

4

我意识到这是一个旧问题,但我在另一个问题上找到了解决方案 - FaultException.Detail 返回为空

将生成的类从 ErrorDetailType 重命名为 ErrorDetail 意味着我可以迭代错误。

于 2018-04-10T10:36:16.953 回答
3

为了让它工作,我在序列中添加了一个虚拟元素:

<xsd:element name="Errors">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="ErrorDetail" type="error:ErrorDetailType" maxOccurs="unbounded"/>
            <xsd:element name="TestElement" type="xsd:string" minOccurs="0"/>
        </xsd:sequence>

    </xsd:complexType>
</xsd:element>

出于某种原因,允许 WCF 正确序列化故障。这会强制 WCF 生成一个新类“错误”,该类在错误合同中传递。然后,您可以捕获FaultException<Errors>异常并访问ErrorDetailType[].

于 2016-10-25T20:19:16.653 回答
0

最终我找到的解决方案是修改 WSDL,以便<detail />不定义元素的内容并用于svcutil生成代理类。当我这样做时,我可以访问原始<err:Errors />XML 元素:

var fault = ex.CreateMessageFault();
var faultXml = fault.GetDetail<XmlElement>();

这允许我使用 XPath 来获取 err:Description 元素的内容。使用原始的 WSDL,我什么也得不到。

于 2015-03-23T14:16:35.740 回答