WCF с сервисом UPS RateWS FaultException.Detail<T> всегда пустой массив

У меня проблема с получением элемента детализации ошибки soap 1.1 с помощью WCF-клиента.NET 4.5 для службы UPS RateWS.

Проблема в том, что в то время как элементы кода ошибки и строки ошибок возвращаются нормально, .Code а также .Message свойства на исключение. Объект detail не десериализован правильно и всегда является пустым массивом.

Я создаю клиент WCF, распаковывая wsdl и xsds из каталога разработчика Rates_Pkg_Gnd.zip файла UPS Rating и указываю на диалог Add Service Reference для Visual Studio 2013s на RateWS.wsdl в моей файловой системе.

Фактическое сообщение о неисправности проводного мыла выглядит следующим образом:

<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] - нулевого размера.

Точно так же ловить FaultException и звонит .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>

3 ответа

Решение

В конечном итоге решение, которое я нашел, было изменить WSDL так, чтобы содержимое <detail /> элемент не определен и используется svcutil генерировать прокси-классы. Когда я делаю это, я получаю доступ к сырой <err:Errors /> Элемент XML:

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

Это позволяет мне использовать XPath для получения содержимого элемента err:Description. С оригинальным WSDL я ничего не получаю.

Я понимаю, что это старый вопрос, но я нашел решение по другому вопросу - FaultException.Detail возвращается пустым

Переименование сгенерированного класса из ErrorDetailType в ErrorDetail означало, что я мог бы повторить ошибки.

Чтобы заставить это работать, я добавил фиктивный элемент в последовательность:

<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[],

Другие вопросы по тегам