Question

I'm developing a WCF application, and one of my services needs to consume a 3rd party web service developed in Java. The 3rd party service is provided by government and it's almost impossible to reach its code / ask for change.

I added it as a Service Reference from its wsdl, and the reference is generated automatically.

The method call seems to work but when I try to catch faults, I'm unable to obtain the custom fault data provided by the 3rd party service. All I can get in FaultException is "Fault occurred while processing." (message and reason are both set only with this.)

The wsdl has a custom fault type, but it looks like .NET cannot map the returned SOAP response to a FaultException with that type. So, my code just gets a generic FaultException with a generic message and HasDetails=false.

Well, this is an issue for us since we are obliged to show our clients what type of fault was returned from the government's web service.

Do you guys think I'm messing with something beatable? Any advise is highly appreciated as I'm already frustrated. Here is a chunk from my code:

try
{
    //this is the 3rd party Java web service
    EFaturaPortTypeClient efService = new EFaturaPortTypeClient();

    //setting here the object to be sent to the 3rd party web service

    var returnVal = efService.sendDocument(docRequest);
}
catch (FaultException<EFaturaFaultType> ex)
{
    //need to get the "Reason" or "Detail" from the returned soap fault
    //but cannot even get in here
}
catch (FaultException ex)
{
    //this is where the debug goes

    //tried below method, but retrieves nothing worthy
    MessageFault mf = ex.CreateMessageFault();

    throw new FaultException<EFaturaFaultType>(mf.GetDetail<EFaturaFaultType>());
}

And here is a SOAP response of fault I sniffed:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
   <soap:Body>
      <soap:Fault>
         <soap:Code>
            <soap:Value>soap:Receiver</soap:Value>
         </soap:Code>
         <soap:Reason>
            <soap:Text xml:lang="en">2006:GECERSIZ ZARF ADI</soap:Text>
         </soap:Reason>
         <soap:Detail>
            <ns3:EFaturaFault xmlns:ns3="http://gib.gov.tr/vedop3/eFatura" xmlns:xmime="http://www.w3.org/2005/05/xmlmime">
               <code>2006</code>
               <msg>GECERSIZ ZARF ADI</msg>
            </ns3:EFaturaFault>
         </soap:Detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

and finally here is the wsdl of the 3rd party web service:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="EFatura" targetNamespace="http://gib.gov.tr/vedop3/eFatura" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://gib.gov.tr/vedop3/eFatura" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
<xs:schema targetNamespace="http://www.w3.org/2005/05/xmlmime" version="1.0" xmlns:tns="http://www.w3.org/2005/05/xmlmime" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:complexType name="base64Binary">
      <xs:simpleContent>
         <xs:extension base="xs:base64Binary">
            <xs:attribute ref="tns:contentType" />
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:complexType name="hexBinary">
      <xs:simpleContent>
         <xs:extension base="xs:string">
            <xs:attribute ref="tns:contentType" />
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:attribute name="contentType" type="xs:string" />
</xs:schema><xs:schema targetNamespace="http://gib.gov.tr/vedop3/eFatura" version="1.0" xmlns:ns1="http://www.w3.org/2005/05/xmlmime" xmlns:tns="http://gib.gov.tr/vedop3/eFatura" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:import namespace="http://www.w3.org/2005/05/xmlmime" />
   <xs:element name="EFaturaFault" type="tns:EFaturaFaultType" />
   <xs:element name="documentRequest" type="tns:documentType" />
   <xs:element name="documentResponse" type="tns:documentReturnType" />
   <xs:element name="getAppRespRequest" type="tns:getAppRespRequestType" />
   <xs:element name="getAppRespResponse" type="tns:getAppRespResponseType" />
   <xs:complexType name="getAppRespRequestType">
      <xs:sequence>
         <xs:element minOccurs="0" name="instanceIdentifier" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
   <xs:complexType name="getAppRespResponseType">
      <xs:sequence>
         <xs:element minOccurs="0" name="applicationResponse" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
   <xs:complexType name="EFaturaFaultType">
      <xs:sequence>
         <xs:element minOccurs="0" name="code" type="xs:int" />
         <xs:element minOccurs="0" name="msg" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
   <xs:complexType name="documentType">
      <xs:sequence>
         <xs:element minOccurs="0" name="fileName" type="xs:string" />
         <xs:element minOccurs="0" name="binaryData" type="ns1:base64Binary" />
         <xs:element minOccurs="0" name="hash" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
   <xs:complexType name="documentReturnType">
      <xs:sequence>
         <xs:element minOccurs="0" name="msg" type="xs:string" />
         <xs:element minOccurs="0" name="hash" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
</xs:schema>  </wsdl:types>
  <wsdl:message name="EFaturaFaultMessage">
    <wsdl:part element="tns:EFaturaFault" name="EFaturaFaultMessage">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="sendDocument">
    <wsdl:part element="tns:documentRequest" name="document">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getApplicationResponse">
    <wsdl:part element="tns:getAppRespRequest" name="getApplicationResponseRequestPart">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getApplicationResponseResponse">
    <wsdl:part element="tns:getAppRespResponse" name="getApplicationResponseResponsePart">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="sendDocumentResponse">
    <wsdl:part element="tns:documentResponse" name="sendDocumentReturn">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="EFaturaPortType">
    <wsdl:operation name="getApplicationResponse">
      <wsdl:input message="tns:getApplicationResponse" name="getApplicationResponse">
    </wsdl:input>
      <wsdl:output message="tns:getApplicationResponseResponse" name="getApplicationResponseResponse">
    </wsdl:output>
      <wsdl:fault message="tns:EFaturaFaultMessage" name="EFaturaFaultMessage">
    </wsdl:fault>
    </wsdl:operation>
    <wsdl:operation name="sendDocument">
      <wsdl:input message="tns:sendDocument" name="sendDocument">
    </wsdl:input>
      <wsdl:output message="tns:sendDocumentResponse" name="sendDocumentResponse">
    </wsdl:output>
      <wsdl:fault message="tns:EFaturaFaultMessage" name="EFaturaFaultMessage">
    </wsdl:fault>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="EFaturaSoapBinding" type="tns:EFaturaPortType">
    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getApplicationResponse">
      <soap12:operation soapAction="getApplicationResponse" style="document" />
      <wsdl:input name="getApplicationResponse">
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getApplicationResponseResponse">
        <soap12:body use="literal" />
      </wsdl:output>
      <wsdl:fault name="EFaturaFaultMessage">
        <soap12:fault name="EFaturaFaultMessage" use="literal" />
      </wsdl:fault>
    </wsdl:operation>
    <wsdl:operation name="sendDocument">
      <soap12:operation soapAction="sendDocument" style="document" />
      <wsdl:input name="sendDocument">
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output name="sendDocumentResponse">
        <soap12:body use="literal" />
      </wsdl:output>
      <wsdl:fault name="EFaturaFaultMessage">
        <soap12:fault name="EFaturaFaultMessage" use="literal" />
      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="EFatura">
    <wsdl:port binding="tns:EFaturaSoapBinding" name="EFaturaSoap12">
      <soap12:address location="https://merkeztest.efatura.gov.tr/EFaturaMerkez/services/EFatura" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Edit: Relevant part from auto generated Reference.cs:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.18408")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://gib.gov.tr/vedop3/eFatura", TypeName = "EFaturaFaultType")]
public partial class EFaturaFaultType : object, System.ComponentModel.INotifyPropertyChanged {

    private int codeField;

    private bool codeFieldSpecified;

    private string msgField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
    public int code {
        get {
            return this.codeField;
        }
        set {
            this.codeField = value;
            this.RaisePropertyChanged("code");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool codeSpecified {
        get {
            return this.codeFieldSpecified;
        }
        set {
            this.codeFieldSpecified = value;
            this.RaisePropertyChanged("codeSpecified");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
    public string msg {
        get {
            return this.msgField;
        }
        set {
            this.msgField = value;
            this.RaisePropertyChanged("msg");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0"
[System.ServiceModel.ServiceContractAttribute(Namespace="http://gib.gov.tr/vedop3/eFatura", ConfigurationName="EFService.EFaturaPortType")]
public interface EFaturaPortType {

    [System.ServiceModel.OperationContractAttribute(Action="sendDocument", ReplyAction="*")]
    [System.ServiceModel.FaultContractAttribute(typeof(BF.EFService.EFaturaFaultType), Action="sendDocument", Name="EFaturaFault")]
    [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
    BF.EFService.sendDocumentResponse sendDocument(BF.EFService.sendDocument request);
Was it helpful?

Solution

I actually solved this by right clicking on the service reference node in the solution explorer in Visual Studio and checking the box Always generate message contracts. Don't ask me how I got there... I could only explain if I knew. The generated classes and methods change after that, and the problem disappears. Although, apparently, it still isn't specific on errors caused by null parameters passed through the generated service proxy.

I hope it helps.

OTHER TIPS

I think you may need to define, if you haven’t already, the EFaturaFaultType class with the DataContract attribute and mark any serializable members with the DataMember attribute.

The following link provides a solid overview of WCF Error Handling. http://www.codeproject.com/Articles/26320/WCF-Error-Handling-and-Fault-Conversion

Regards,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top