none
passing Complex Type parramenters for SOAP Webservice in C# RRS feed

  • Question

  • Hello all
    I am new to web services and I am trying to figure out how to pass values to the web service. I already tested the web service using Boomerang and I know it is working. I just cant figure out how to pass the values it needs to generate the XML. 

    Here is the WSDL file

    <WL5G3N0:types>
    <xs:schema xmlns:WL5G3N2="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:WL5G3N1="xxxxxxx" xmlns:WL5G3N0="http://schemas.xmlsoap.org/wsdl/" targetNamespace="java:com.ams.sacwis.mobile.services" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="testServiceForm">
    <xs:sequence>
    <xs:element name="input1" type="xs:string" nillable="true" minOccurs="1"/>
    <xs:element name="input2" type="xs:string" nillable="true" minOccurs="1"/>
    <xs:element name="input3" type="xs:string" nillable="true" minOccurs="1"/>
    <xs:element name="input4" type="xs:string" nillable="true" minOccurs="1"/>
    <xs:element name="input5" type="xs:string" nillable="true" minOccurs="1"/>
    </xs:sequence>
    </xs:complexType>
    </xs:schema>
    <xs:schema xmlns:WL5G3N2="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:WL5G3N1="xxxxxxx" xmlns:WL5G3N0="http://schemas.xmlsoap.org/wsdl/" targetNamespace="xxxxxxxxxx" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:import namespace="java:com.ams.sacwis.mobile.services"/>
    <xs:element name="testService">
    <xs:complexType>
    <xs:sequence>
    <xs:element name="s_form" type="java:testServiceForm" xmlns:java="java:com.ams.sacwis.mobile.services"/>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    <xs:element name="testServiceResponse">
    </xs:schema>
    </WL5G3N0:types>

    Here is what the XML needs to look like : 

    <x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mob="xxxxxxx" xmlns:jav="java:com.ams.sacwis.mobile.services">
        <x:Header/>
        <x:Body>
            <mob:testService>
                <mob:s_form>
                    <jav:input1>test1</jav:input1>
                    <jav:input2>
                        <![CDATA[      <Form1>       <Element1>abc</Element1>       <Element2>abc</Element2>      </Form1>      ]]> 
                    </jav:input2>
                    <jav:input3>
                        <![CDATA[      <Form2>       <Element3>12345</Element3>      </Form2>  ]]>
                    </jav:input3>
                    <jav:input4>?</jav:input4>
                    <jav:input5>?</jav:input5>
                </mob:s_form>
            </mob:testService>
        </x:Body>
    </x:Envelope>

    Here is what I've coded after adding the service reference:

     protected void Login_Btn_Click(object sender, EventArgs e)
            {
                String input1 = "test1";
    	    String input2 = "<![CDATA[<Form1><Element1>abc</Element1><Element2>abc</Element2></Form1>]]> ";           
                String input3 = "<![CDATA[<Form2><Element3>12345</Element3></Form2>]]>";
    	    String input4 = "?";
    	    String input5 = "?";
                
                a.PortTypeClient client = new a.PortTypeClient();
    
                var response = client.testService(input1,input2,input3,input4,input5);
    
                Response_Lbl.Text = response.ToString();
    
            }

    but i get on this line : client.testService(....) = cannot convert from string to a.testService.testServiceForm

    I will really appreciate any guidance you can provide, thank you


    Wednesday, January 15, 2020 6:56 PM

All replies

  • I updated my code to : 

    var response = client.testService(new testService.testServiceForm { input1 = input1, input2 = input2, input3 = input3, input4 = input4, input5 = input5 });

    This allowed the call to be made but now the other end is closing the connection : 

    System.ServiceModel.CommunicationException: 'An error occurred while making the HTTP request to xxxxxxx. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.'

    (xxxxx = replaced with the actual webserver address for security reasons)

    I have tested the address using the Boomerang plugin on which you write the XML and send via POST and it works as expected. So Im sure the webservice is working... just not sure what I am sending....

    Any help will be really appreciated!!!

    Wednesday, January 15, 2020 10:30 PM
  • Hi,
    Adding service reference not only generates a client proxy class/data contract class but also add some configurations in the appconfig file.
    The errors seem to me that the service might not work properly over https protocol. For instance, the backend service only works over Http protocol. thereby calling to the Https service endpoint is invalid. Alternatively, there might be something wrong with a mismatch of the service binding between the client-side and the server-side.
    I would like to know that configuration in the configuration file. Moreover, we could use SVCUtil.exe tool to generate the client proxy class and configurations.
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
    Feel free to let me know if the problem still exists.
    Best Regards
    Abraham

    Thursday, January 16, 2020 8:15 AM
    Moderator
  • Thank you for your response Abraham,

    I tried SVCUtil.exe and I get the same error message. This leads me to believe something might be wrong between their WSDL and the actual webservice

    on Boomerang when I tried to configure the service I had to type the following : 

    -as per the instruction document from the webservice destination : 

    The location of the WSDL (eg. https://xxxxxxx.us/test/testService?WSDL)
    • The location of the mobile endpoint (eg. https://xxxxxxx.us/test/testService)

    This did not work, but if I change it to :

    The location of the WSDL (eg. http://xxxxxxx.us/test/testService?WSDL)

    Then it did work, then when I do the actual POST I do it to : 
    https://xxxxxxx.us/test/testService

    and not https://xxxxxxxx.us:9002/test/testService which is what the endpoint defaults to when it pulls the data from the WSDL.

    Now that being said, I attempted the same thing in Visual Studio by pulling the WSDL from the 
    http://xxxxxxx.us/test/testService?WSDL via the "Add Service Reference" and then going into the Web.Config of the project and updating the endpoint client to what I know works which is https://xxxxxxx.us/test/testService and NOT https://xxxxxxx.us:9002/test/testService which is what the WSDL populates.

    Me being new I didn't think any of this when I was configuring it as I thought it would just work as it did in Boomerang. 

    Based on what I've explained above... do you see any way I could force the POST to be to the address, or where in my project I can go to update the job to match the configuration that does work?

    Thank you for your help :)

    Thursday, January 16, 2020 2:59 PM
  • Hi,

    When we instantiate the client proxy, It will automatically take the service endpoint section in the configuration file.

    ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();


    And the client section in the configuration file.

        <client>
          <endpoint address="http://10.157.13.69:21011/" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
            name="BasicHttpBinding_IService" />
    </client>


    Feel free to let me know if the problem still exists.
    Best Regards
    Abraham

    Friday, January 17, 2020 9:34 AM
    Moderator
  • Hi Abraham, Thanks for your reply

    When you say configuration file do you mean Web.Config in the project or some other config file?

    if its the Web.Config this is where I've replaced the endpoint address with the working path (working in Bommerang and SOAPUI 5.5) (https://xxxxxxx.us/test/testService) but the response is killed with the following message (see below) which is the same error I get when I use svcutil

    ----------------------------------------

    URI: https://xxxxxx.us/test/testService
        Metadata contains a reference that cannot be resolved: 'https://xxxxxx.us/test/testService'.

        An error occurred while making the HTTP request to https://xxxxxx.us/test/testService. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.

        The underlying connection was closed: An unexpected error occurred on a send.
        Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
        An existing connection was forcibly closed by the remote host

    ---------------------------------------------------

    if I do it without changing the endpoint this is the message I get: 

    ---------------------------------------------------

    There was no endpoint listening at https://xxxxxx.us:9002/test/testService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
        Unable to connect to the remote server
        A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xxxxx:9002

    ---------------------------------------------------

    Any idea why it works with using a client (boomerang or SOAPUI) but doesn't when using visual studio or cmd/svcutil?

    Thank you!

    Friday, January 17, 2020 2:23 PM
  • If I were going to pass complex types from a Web service client to a Web service method, I would use the DTO pattern.

    https://en.wikipedia.org/wiki/Data_transfer_object

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    Using the DTO embodies using encapsulation and information hiding.

    https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)

    Saturday, January 18, 2020 9:09 PM
  • Hi DA924x

    Thank you for your response, I'm totally new to webservices but I sort of get why using DTO would benefit sending data. 

    Now I think the first issue I have to solve here is the particular connection to the webservice. The communication between me and them. Right now it works using a utility (boomerang or SOUPUI) and not via the code or even cmd utility SVCUtil.exe.

    So I cant even send the message. I think once I figure out the pathway, then I can modify the wrapping method. I'm very like incorrect here but the way I see it and so far understand it.

    Here is the issue : 

    1. We have a client that provides us with data, to provide this data they setup a SOAP messaging protocol

    2. The service works perfectly using the utility SOUPUI 5.5.0

    3. The service Fails when I try SVCUtil.exe

    ----------------------------------------

    URI: https://xxxxxx.us/test/testService
        Metadata contains a reference that cannot be resolved: 'https://xxxxxx.us/test/testService'.

        An error occurred while making the HTTP request to https://xxxxxx.us/test/testService. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.

        The underlying connection was closed: An unexpected error occurred on a send.
        Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
        An existing connection was forcibly closed by the remote host

    ---------------------------------------------------

    4. The service fails when I try to use c# code.

    --------------------------------------------------

     string MethodNm = Method_Txt.Text;
                string Usernm = Username_Txt.Text;
                string Passwd = Password_Txt.Text;
                string LoginId = LoginId_Txt.Text;
                string CDDATA1 = "<![CDATA[< mobileLogonForm ><username>" + Usernm + "</username>" + "<password>" + Passwd + "</password>" + "</mobileLogonForm>]]>";
                string CDDATA2 = "<![CDATA[< assignedCaseListInputForm >< loginId >" + LoginId +  "</ loginId ></ assignedCaseListInputForm >]] >";
    
                string[] P_List = { MethodNm, CDDATA1, CDDATA2, "?", "?" };
    
                mobileService3.MobileServicePortTypeClient client = new mobileService3.MobileServicePortTypeClient();
                //Results_Lbl.Text = string.Join(",", P_List); //*FOR TESTING ONLY**  this will just show the contents of the array we are trying to push in
    
    
           
                //----------------------FRAMEWORK PROCESS-------------------------------
                var response = client.mobileService(new mobileService3.MobileServiceForm { methodName = MethodNm, loginXML = CDDATA1, inputXML = CDDATA2, outputXML = "?", exceptionXML = "?" });
                Results_Lbl.Text = "" + response;
                


    -------------------------------------------------


    • Edited by Syrom Thursday, January 30, 2020 2:28 PM
    Thursday, January 30, 2020 2:26 PM
  • 1. We have a client that provides us with data, to provide this data they setup a SOAP messaging protocol

    Do you mean you have a client that has a Web service that sends your company data? If so, then you need to talk to the client about how to successfully consume its Web service.

    Friday, January 31, 2020 4:40 AM
  • Hi DA924x

    Thank you for your quick reply.

    As far as reaching out to the client it is not possible as it is a government agency and the webservice was established a good while ago by a third party. So there is no point of contact, when we reach out they just provide a guide that the person that established the service created.

    I am sure the webservice is working as others in our industry are using it. Also when using Boomerang and SoapUI it returns the expected result. So to me that discards the connection issue... So it must be at the code level.

    Today I tried writing the actual SOAP envelope message and trying via HttpWebRequest but still no luck...

    This is exactly what the service is expecting:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mob="xxxxxxxxxxxxxxx" xmlns:java="java:com.ams.sacwis.mobile.services">
       <soapenv:Header/>
       <soapenv:Body>
          <mob:mobileService>
             <mob:p_form>
                <java:methodName>getOrgWorkerRoleList</java:methodName>
                <java:loginXML><![CDATA[<mobileLogonForm><username>xxxx</username><password>xxxx</password></mobileLogonForm>]]></java:loginXML>
                <java:inputXML>&lt;workerInfoInputForm>&lt;loginId>xxxx&lt;/loginId>&lt;/workerInfoInputForm></java:inputXML>
                <java:outputXML>?</java:outputXML>
                <java:exceptionXML>?</java:exceptionXML>
             </mob:p_form>
          </mob:mobileService>
       </soapenv:Body>
    </soapenv:Envelope>

    here is the code I was trying : 

    string soap = @"<?xml version=""1.0"" encoding=""utf-8""?> <soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:mob=""xxxxxxxxxx"" xmlns:jav=""java:com.ams.sacwis.mobile.services""> <soap:Header/> <soap:Body> <mob:mobileService> <mob:p_form> <jav:methodName>getAssignedCaseList</jav:methodName> <jav:loginXML><![CDATA[<mobileLogonForm><username>xxxx</username><password>xxxxxxx</password></mobileLogonForm>]]></jav:loginXML> <jav:inputXML><![CDATA[<assignedCaseListInputForm><loginId>xxxx</loginId></assignedCaseListInputForm>]]></jav:inputXML> <jav:outputXML>?</jav:outputXML> <jav:exceptionXML>?</jav:exceptionXML> </mob:p_form> </mob:mobileService> </soap:Body> </soap:Envelope>"; HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create("xxxxxxx"); myRequest.ContentType = "text/xml;charset=\"utf-8\""; myRequest.Method = "POST"; using (Stream stm = myRequest.GetRequestStream()) { using (StreamWriter stmw = new StreamWriter(stm)) { stmw.Write(soap); } HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse; StreamReader reader = new StreamReader(response.GetResponseStream()); Response.Write(reader.ReadToEnd()); reader.Close();

    }

    On the underline row I get the following error : 

    Server Error in '/' Application.

    An existing connection was forcibly closed by the remote host

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

    Source Error:
    Line 74: 
    Line 75:                 HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse;
    Line 76:                 StreamReader reader = new StreamReader(response.GetResponseStream());
    Line 77:                 Response.Write(reader.ReadToEnd());

    Source File: C:\inetpub\wwwroot\mobileSolution\FSFN_mobileSolution\FSFN_webservice.aspx.cs    Line: 75

    Stack Trace:
    [SocketException (0x2746): An existing connection was forcibly closed by the remote host]
       System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) +111
       System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) +131
    
    [IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
       System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) +299
       System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) +32
       System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) +164
       System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) +297
       System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) +51
       System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) +166
       System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) +573
       System.Net.TlsStream.CallProcessAuthentication(Object state) +44
       System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) +195
       System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) +22
       System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) +67
       System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result) +803
       System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size) +54
       System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size) +105
       System.Net.ConnectStream.WriteHeaders(Boolean async) +449
    
    [WebException: The underlying connection was closed: An unexpected error occurred on a send.]
       System.Net.HttpWebRequest.GetResponse() +1463
       FSFN_mobileSolution._Default.Process_Btn_Click(Object sender, EventArgs e) in C:\inetpub\wwwroot\mobileSolution\FSFN_mobileSolution\FSFN_webservice.aspx.cs:75
       System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9784114
       System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +211
       System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +12
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +15
       System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1696
    





    • Edited by Syrom Friday, January 31, 2020 6:30 PM
    Friday, January 31, 2020 6:13 PM
  • Have you tried to use HTTPClient()?
    Saturday, February 1, 2020 9:05 AM
  • Hi DA924X

    Thank you for your response. For my latest attempt. I went ahead and change languages to VB.NET but still getting an error : 

    IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

    I will try to open another Question for vb.net.

    Thank you

    Tuesday, February 4, 2020 9:27 PM
  • Hi DA924X

    Thank you for your response. For my latest attempt. I went ahead and change languages to VB.NET but still getting an error : 

    IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

    I will try to open another Question for vb.net.

    Thank you

    What lead you to using HttpWebResponse? Was it part of the documentation on how to consume the service?
    Sunday, February 9, 2020 1:40 AM
  • Hi DA924x

    Well I actually was trying any method to be able to consume the service. As I couldn't generate the envelope via Visual Studio I decided to maybe try to construct the envelope manually. Anyways I was able to resolve the issue. Although I changed coding into aspx.vb I will post my code in case it can help someone in the future. In summary it came down to two things. First I was parsing the envelope incorrectly and second there was an issue with my Visual Studio project. 

    The way I was able to resolve was by contacting the webservice provider and asking if they were getting my traffic and what they were seeing. They were able to provide a log of what my envelope looked like on their end. And I created a new project to make sure me adding and removing the service reference so many times hadn't affected anything

    Here is my code: (what is commented out was the way I was trying before)

    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim loginXML As String, InputXML As String, MethodName As String, OutputXML As String, ExceptionXML As String MethodName = txtMethodNm.Text.Trim 'loginXML = "<![CDATA[<mobileLogonForm><username>" & txtUserId.Text.Trim & "</username><password>" & txtPassword.Text.Trim & "</password></mobileLogonForm>]]>"' loginXML = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" & vbCrLf loginXML = loginXML + "<mobileLogonForm>" & vbCrLf loginXML = loginXML + " <username>" & txtUserId.Text.Trim & "</username>" & vbCrLf loginXML = loginXML + " <password>" & txtPassword.Text.Trim & "</password>" & vbCrLf loginXML = loginXML + "</mobileLogonForm>" & vbCrLf 'InputXML = "<![CDATA[<workerInfoInputForm><loginId>" & txtInputVar.Text.Trim & "</loginId></workerInfoInputForm>]]>"' InputXML = "<?xml version='1.0' encoding='UTF-8'?>" InputXML = InputXML + "<workerInfoInputForm>" & vbCrLf InputXML = InputXML + " <loginId>" & txtInputVar.Text.Trim & "</loginId>" & vbCrLf InputXML = InputXML + "</workerInfoInputForm>" & vbCrLf OutputXML = "?" ExceptionXML = "?" InvokeWebService(MethodName, loginXML, InputXML, OutputXML, ExceptionXML) End Sub

    Private Sub InvokeWebService(ByVal arg1 As String, ByVal arg2 As String, ByVal arg3 As String, ByVal arg4 As String, ByVal arg5 As String)
            Dim mobileservice As New webservice.MobileService
            Dim mobileFormIn As New webservice.MobileServiceForm()
            Dim mobileFormOut As New webservice.MobileServiceForm
    
            mobileFormIn.methodName = arg1
            mobileFormIn.loginXML = arg2
            mobileFormIn.inputXML = arg3
            mobileFormIn.outputXML = arg4
            mobileFormIn.exceptionXML = arg5
    
            mobileservice.SoapVersion = Services.Protocols.SoapProtocolVersion.Soap11
            mobileservice.AllowAutoRedirect = True
            mobileservice.Url = "xxxxx"
    
            mobileFormOut = mobileservice.mobileService(mobileFormIn)
    
            Dim Result = mobileFormOut.outputXML.ToString
    
            lblResults.Text = Result.ToString
    
            
    
        End Sub


    Thank you for the help!


    • Edited by Syrom Wednesday, February 12, 2020 2:04 PM
    Wednesday, February 12, 2020 1:59 PM