MDrivenWiki
Log in

SOAP

From MDrivenWiki

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 soap-envelope that is returned from the called service.

SoapCalls take a action (above 'GetQuote') and set this 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 underscore '_' denotes "No namespace"

The Definition above gives this envelope - note that in the example we try to use 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 below - if you send in a 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 prior to sending it.