SOAP

Call SOAP service like this:

vNewVar:=selfVM.SoapCall('http://www.webserviceX.NET/stockquote.asmx','GetQuote','http://www.webserviceX.NET/','','','NestingWParams')

SoapCall returns the body of the soapEnvelope that is returned from the called service.

SoapCalls take an action (above 'GetQuote') and set it as SOAPAction header - the action is also included in the request body.

2019-10-18 12h47 09.png

(1 and 3) Root ViewModel columns of type String starting with 'ns' will be treated as namespaces for the request.

(2) If the Root ViewModelColumn named ClientCertThumbPrint is found, we will look up the cert and use it in the call.

  • Starting a column with an underscore '_' denotes "No namespace".

The definition above gives this envelope. Note that in the example, we try to use a standard nsAction namespace, no namespace, or an addition namespace:

<?xml version = '1.0'  encoding='utf-8' ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<soap:Header>
		<wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" >
			<wsse:UsernameToken wsu:Id="UsernameToken-123"  >
				<wsse:Username>auser</wsse:Username>
				<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" >apwd</wsse:Password>
				<wsu:Created>2019-10-18T09:07:21Z</wsu:Created>
			</wsse:UsernameToken>
		</wsse:Security>
	</soap:Header>
	<soap:Body  xmlns:nsAction="TheNameSpace">
		<nsAction:TheAction>
			<nsAction:SomeString>Hello</nsAction:SomeString>
			<SomeString>Hello</SomeString>
			<nsAdditionalNameSpace:SomeString xmlns:nsAdditionalNameSpace="AdditionalNameSpaceAdded">Hello</nsAdditionalNameSpace:SomeString>
		</nsAction:TheAction>
	</soap:Body>
</soap:Envelope>

We build the soapEnvelope for the request with code like the one below. If you send in an action namespace, we use it accordingly.

      StringBuilder soapenvelopebuilder = new StringBuilder();
      soapenvelopebuilder.Append(@"<?xml version = '1.0'  encoding='utf-8' ?>");
      soapenvelopebuilder.Append(@"<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">");
      soapenvelopebuilder.Append(soapheaderbuilder);
      soapenvelopebuilder.Append("  <soap:Body " + @" xmlns:nsAction=""" + actionnamespace + @""">");
      soapenvelopebuilder.Append(@"    <nsAction:" + action + ">");
      soapenvelopebuilder.Append(parametersForSoapCall);
      soapenvelopebuilder.Append(@"   </nsAction:" + action + @">");
      soapenvelopebuilder.Append("  </soap:Body>");
      soapenvelopebuilder.Append("</soap:Envelope>");

In the code above, we see the parametersForSoapCall. This is defined as below:

    private StringBuilder GetParamsForSoapCall(ViewModelReferenceType vmref, string nestingWithParams)
    {
      StringBuilder parametersForSoapCall = new StringBuilder();
      if (!string.IsNullOrEmpty(nestingWithParams))
      {


        ViewModelClass vmc;
        if ((vmref.Value as ViewModel).AllViewModelClasses.TryGetValue(nestingWithParams, out vmc))
        {

          var root = (vmref.Value as ViewModel).GetOclVariableValueFromName(vmc.NameOfCurrentVariable_Ocl());
          if (root != null && root.AsObject == null && (vmref.Value as ViewModel).RootObject != null)
            root = (vmref.Value as ViewModel).RootObject.AsIObject();

          DoSoapCallParamForRoot(vmref, root, vmc, parametersForSoapCall);
        }
      }
      return parametersForSoapCall;
    }

    private void DoSoapCallParamForRoot(ViewModelReferenceType vmref, IElement root, ViewModelClass vmc, StringBuilder parametersForSoapCall)
    {
      // find potential namespace columns
      Dictionary<string, string> namespaces = new Dictionary<string, string>();
      foreach (var col in vmc.ViewModel.RootViewModelClass.Columns)
      {
        if (col.RuntimeName.StartsWith("ns") && col.ExpressionResultType != null && col.ExpressionResultType.ObjectType == typeof(string))
        {
          namespaces.Add(col.RuntimeName, EcoServiceHelper.GetEcoService<IOclService>((vmref.Value as ViewModel).EcoServiceProvider).Evaluate(root, col.Expression, (vmref.Value as ViewModel).GetIExternalVariableList()).AsObject as string);
        }
      }

      foreach (var col in vmc.Columns)
      {
        var colresult = EcoServiceHelper.GetEcoService<IOclService>((vmref.Value as ViewModel).EcoServiceProvider).Evaluate(root, col.Expression, (vmref.Value as ViewModel).GetIExternalVariableList());
        if (colresult != null)
        {
          var nsForParam = "nsAction:";
          var colnamewithoutns = col.RuntimeName;
          var nsdef = "";
          var nameparts = colnamewithoutns.Split('_');
          if (nameparts.Count() > 1)
          {
            if (namespaces.ContainsKey(nameparts[0]))
            {
              nsForParam = nameparts[0] + ":";
              colnamewithoutns = colnamewithoutns.Replace(nameparts[0] + "_", "");
              nsdef = " xmlns:" + nameparts[0] + "=" + @"""" + namespaces[nameparts[0]] + @"""";
            }
            else
            {
              nsdef = "";
              nsForParam = ""; // blank namespace
            }

          }

          if (col.DetailAssociation != null)
          {
            // Allow for structures in input
            string paramline = "";
            StringBuilder parametersForNesting = new StringBuilder();
            DoSoapCallParamForRoot(vmref, root, col.DetailAssociation, parametersForNesting);
            paramline = "<" + nsForParam + colnamewithoutns + nsdef + ">" + parametersForNesting.ToString() + "</" + nsForParam + colnamewithoutns + ">";
            parametersForSoapCall.Append(paramline);
          }
          else
          {
            string paramline = "";
            //<SomeParam xsi:type=""xsd:integer"">12</SomeParam>
            var value = colresult.AsObject;
            if (value != null)
            {
              paramline = value.ToString();
            }
            paramline = "<" + nsForParam + colnamewithoutns + nsdef + ">" + paramline + "</" + nsForParam + colnamewithoutns + ">";
            parametersForSoapCall.Append(paramline);
          }
        }
      }
    }

Special Variables

ViewModel variable named vSoapDebug – when we find this in the ViewModel, we assign the complete SoapEnvelope to this before sending it.

vSoapResult: String - the returned value from the service - we will try to convert this to xml

vSoapError:String - if we get an exception during parsing of response we set the value here

This page was edited 161 days ago on 06/17/2024. What links here