Search code examples
wcfsoapinputwsdloperation

SOAP - WCF: OperationContract not receiving input parameters


I am building a new SOAP API in WCF to replace old service in an already established communication with client server. The catches here are:

  • I am not allowed to edit the client side
  • Current API (the one I am replacing) is very old and generates everything in wsdl file, not singleWsdl and wsdl

I managed to establish a connection to the client and my operation is being called, but I am receiving no input parameters. I am sure the parameters are being sent because I have another solution which is working like the current client for my testing purposes. When it's pointing to the old API, it all works fine and inputs are sent, but when I point it to my API it only calls the operation but without inputs as mentioned.

I added Service References to each of the APIs in my test solution to see the differences and I noticed the namespace of the input complex type is different, but here is my current problem: The name of the operation is the same as the name of the complex type it takes as an input parameter and they both need to be on the same namespace (I presume). I didn't expect this to be a problem, but in my singleWsdl file I can see all my operations listed also as elements in <types> and their input nested as <complexType>s.

I am also wondering whether the problem are imports in my wsdl file or the simple fact I am replacing old wsdl file structure in already establish communication with new wsdl/singleWsdl file structure and it doesn't know where to look for the complex types.

old API Reference.cs (added Service Reference as Web Reference):

[System.Web.Services.Protocols.SoapRpcMethodAttribute("http://www.namespaceURL.com/InternalApi/UpdateScheduler", RequestNamespace="http://www.namespaceURL.com/InternalApi", ResponseNamespace="http://www.namespaceURL.com/InternalApi", Use=System.Web.Services.Description.SoapBindingUse.Literal)]
    [return: System.Xml.Serialization.XmlElementAttribute("return")]
    public returnUpdateScheduler UpdateScheduler([System.Xml.Serialization.XmlElementAttribute("UpdateScheduler")] UpdateScheduler UpdateScheduler1) {
        object[] results = this.Invoke("UpdateScheduler", new object[] {
                    UpdateScheduler1});
        return ((returnUpdateScheduler)(results[0]));
    }

new singleWsdl file types:

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.namespaceURL.com/InternalApi">
    <xs:import namespace="http://schemas.datacontract.org/2004/07/PairLeague"/>
    <xs:element name="UpdateScheduler">
      <xs:complexType>
        <xs:sequence>
          <xs:element minOccurs="0" name="UpdateScheduler" nillable="true" type="tns:UpdateScheduler"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:schema>
</wsdl:types>

new wsdl file imports:

<wsdl:types>
  <xsd:schema targetNamespace="http://www.namespaceURL.com/Imports">
    <xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd0" namespace="http://www.namespaceURL.com/InternalApi" />
    <xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
    <xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/PairLeague" />
  </xsd:schema>
</wsdl:types>

This is my first time working with SOAP and WCF so my understanding might be incorrect or I might be simply looking at a wrong place. If anybody have any sort of idea, I would be very grateful if you shared it with me please.


Solution

  • The final solution was to set OperationFormatStyle of [ServiceContract] to 'Rpc'

    [ServiceContract(Namespace = "http://www.example.com/Service"),
     XmlSerializerFormat(Style = OperationFormatStyle.Rpc)]
    

    It seems like when trying to establish a connection with 3rd party service, you need to use the same names and namespaces as well as match the same message structure. Since I am mimicking a SOAP interface of RPC structure, I am not allowed to use MessageContracts, but I need to specify the structure of the messages in which DataContracts are being sent. By setting the style parameter to RPC, DataContracts (ComplexTypes) in wsdl get formatted in message tags correctly. Without the style set to Rpc my operation was not recognising any input type parameter and when I set the DataContract as MessageContract, the input type was recognised, but never populated with passed values when the operation was called. Please note this is just my deduction based on experimenting with the code, the true reason why it now works might be completely different, but most importantly for me now - it's working!

    My message element in wsdl was also automatically formated which included incorrect name and namespace parameters. In my case the name included the namespace of my project, service name and the specific operation name whereas I needed it to be only the operation name.

    I also focused on producing only one big wsdl file without any includes as the 3rd party service is expecting this format. At the moment it didn't seem to give me any problems, but it is possible I would encounter a problem there later in the process.

    My solution in this matter was implementation of WCFExtrasPlus package through NuGet. In Visual Studio you can open NuGet package Manager through Project panel menu and search for WCFExtrasPlus package and install it.

    To set your project to use the package I followed these notes:

    http://george2giga.com/development/wcf-merge-wsdl-in-a-single-file/