Reputation: 19
We use Azure APIM for hosting our SOAP services and integrating the C# code with service endpoints and making calls through HttpClient.We always create elements manually and add values to inner text of element and send it as string content to the service.This is simple for request few elements but when it comes to a huge request we have to spend lot of time in manually creating the soap xml request and is time consuming,error prone? Is there a better approach to send soap request to APIM and parse the soap reaponse?
Upvotes: 0
Views: 1978
Reputation: 227
You can define your SOAP-request body in an liquid template and parse the XML-response and convert it back to json like in this example:
<policies>
<inbound>
<base />
<set-header name="Content-Type" exists-action="override">
<value>text/xml;charset=UTF-8</value>
</set-header>
<set-method>POST</set-method>
<set-body template="liquid">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tim="http://services.test.com/Service">
<soapenv:Header />
<soapenv:Body>
<tim:GetTimesheet>
<tim:input>
<tim:DateTimeFrom>{{context.Request.MatchedParameters["DateTimeFrom"]}}</tim:DateTimeFrom>
<tim:DateTimeTo>{{context.Request.MatchedParameters["DateTimeTo"]}}</tim:DateTimeTo>
<tim:ResourceId>{{context.Request.MatchedParameters["ResourceId"]}}</tim:ResourceId>
</tim:input>
</tim:GetTimesheet>
</soapenv:Body>
</soapenv:Envelope>
</set-body>
<set-backend-service base-url="https://webservices/service.svc" />
<rewrite-uri template="/" copy-unmatched-params="false" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
<xsl-transform>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="* | @* | node()">
<xsl:apply-templates select="@* | node()|*" />
</xsl:template>
<xsl:template match="PeriodList">
<item>
<xsl:for-each select="PeriodType">
<timeSheet>
<DateTimeFrom>
<xsl:value-of select="*[local-name() = 'DateFrom']" />
</DateTimeFrom>
<DateTimeTo>
<xsl:value-of select="*[local-name() = 'DateTo']" />
</DateTimeTo>
<Status>
<xsl:value-of select="*[local-name() = 'Status']" />
</Status>
<EntryList>
<xsl:for-each select="EntryList/Entry/WorkDayList/WorkDay">
<Entry>
<Day>
<xsl:value-of select="Day" />
</Day>
<HoursWorked>
<xsl:value-of select="HoursWorked" />
</HoursWorked>
</Entry>
</xsl:for-each>
</EntryList>
</timeSheet>
</xsl:for-each>
</item>
</xsl:template>
</xsl:stylesheet>
</xsl-transform>
<set-body template="liquid">
[
{%- JSONArrayFor ts in body.item -%}
{
"dateTimeFrom" : "{{ts.timeSheet.DateTimeFrom}}",
"dateTimeTo" : "{{ts.timeSheet.DateTimeTo}}",
"periodId" : "{{ts.timeSheet.PeriodId}}",
"days": [
{%- JSONArrayFor wd in ts.timeSheet.EntryList -%}
{
"day" : "{{wd.Entry.Day}}",
"hoursWorked" : "{{wd.Entry.HoursWorked}}"
}
{%- endJSONArrayFor -%}
]
}
{%- endJSONArrayFor -%}
]
</set-body>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
</outbound>
<on-error>
<base />
</on-error>
</policies>
Upvotes: 0
Reputation: 523
You can write the inbound policy in APIM > API operation before sending sending the request to backend soap service.
Please find the below reference.
<policies>
<inbound>
<base />
<rewrite-uri template="/your_soap_service_url.svc" copy-unmatched-params="false" />
<set-body template="none">@{
string message = context.Request.Body.As<String>(preserveContent:true);
try
{
you can write your logic here, if you want to manipulale your request
}
catch{}
string soapPacketStart = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:yourNamespace=\"namespace url, if you have namespace in your message">
<soap:Header xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">
<wsa:Action>YourAction</wsa:Action>
<wsa:To>https://your_backend_url.svc</wsa:To>
</soap:Header>
<soap:Body>";
string soapPacketEnd ="</soap:Body>
</soap:Envelope>";
message = string.Format("{0}{1}{2}",soapPacketStart,message,soapPacketEnd); //your soap message is ready
return message;
}</set-body>
<set-header name="Content-Type" exists-action="override">
<value>application/soap+xml; Action="YourAction"</value>
</set-header>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
//like wise you can set your response
</outbound>
<on-error>
<base />
</on-error>
</policies>
Upvotes: 1
Reputation: 222582
You can automate it using APIManagementARMTemplateCreator
which extracts ARM templates for your API's to be used in the CI/CD process.
Upvotes: 0