2014-11-24 32 views
0

我遇到了使用.NET 4.5 WCF客戶端用於UPS RateWS服務的soap 1.1故障詳細信息元素的問題。WCF與UPS RateWS服務FaultException.Detail <T>始終爲空陣列

問題是,雖然故障代碼和故障排除元素恢復正常,但是異常時屬性爲.Code.Message。詳細信息對象沒有正確反序列化,並且始終是一個空數組。

我被拆包從UPS Rating developer kit Rates_Pkg_Gnd.zip文件架構的WSDL目錄中的WSDL和XSD和指點的Visual Studio 2013s在RateWS.wsdl添加服務引用對話框我的文件系統上生成的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[]>但詳細屬性始終UPS.RateService.ErrorDetailType [0]的數組 - 大小爲零。

同樣捕獲FaultException並調用.CreateMessageFault()訪問.GetDetail<XmlElement>()會生成一個包含ArrayOfErrorDetailType元素的XML對象,其中不含任何內容。使用.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> 

回答

0

最終,我發現解決方案是修改WSDL使得沒有定義<detail />元素的內容,並使用svcutil生成代理類。當我這樣做,我可以訪問原始<err:Errors /> XML元素:

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

這讓我使用XPath獲取在犯錯的內容:描述元素。有了原始的WSDL,我什麼也得不到。

2

爲了得到這個工作,我添加了一個虛設的元素序列內:

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