Search code examples
xmlazure-api-managementapim

APIM Inbound Policy - Use Set-Body to append an XML element containing child elements at the root level


UPS's api requires credentials in the request body it receives in an element called AccessRequest. Via Azure API Management, I need to inject this into the Inbound Policy along with the existing body content (TrackingRequest). I can save the complete AccessRequest content in Azure Key Vault and inject it in one go using {{AccessRequest}}.

Here is an example of what I want POSTing to their API.

<AccessRequest>
    <AccessLicenseNumber>xxxxxxxxxxxxx</AccessLicenseNumber>
    <UserId>xxxxxxxxxxxxx</UserId>
    <Password>xxxxxxxxxxxxx</Password>
</AccessRequest>
<TrackRequest>
    <Request>
        <TransactionReference>
            <CustomerContext>Your Test Case Summary Description</CustomerContext>
        </TransactionReference>
        <RequestAction>Track</RequestAction>
        <RequestOption>activity</RequestOption>
    </Request>
    <TrackingNumber>1Z6xxxxxxxxxxxxx</TrackingNumber>
</TrackRequest>

My attempt.....

<set-body>@{ 
var requestBody = context.Request.Body.As<JObject>(preserveContent: true);
requestBody [\"Content-Type\"] = \"application/xml\";
requestBody.Append(\"{{AccessRequest}}\");
return requestBody.ToString();
}</set-body>

Hoping this would work but it fails on

Content:
{"error":{"code":"ValidationError","message":"One or more fields 
contain incorrect values:","details": 
[{"code":"ValidationError","target":"set-body","message":"Error in 
element 'set-body' on line 3, column 38: 'JObject' does not contain 
a definition for 'Append' and the best extension method overload 
'Enumerable.Append<string>(IEnumerable<string>, string)' requires a 
receiver of type 'IEnumerable<string>'"}]}}

Solution

  • I have created a named variable which is having below value in it.

    <AccessRequest>
       <AccessLicenseNumber>xxxxxxxxxxxxx</AccessLicenseNumber>
        <UserId>xxxxxxxxxxxxx</UserId>
        <Password>xxxxxxxxxxxxx</Password>
    </AccessRequest>
    

    I am using this below given policy to add AccessRequest element at the top of existing body content of TrackRequest.

    <inbound>
        <base  />
        <set-variable  name="accessRequest"  value="{{AccessRequest}}"  />
        <set-body>@{
            var trackRequest = context.Request.Body.As<string>(preserveContent: true);
            var accessRequest = context.Variables.GetValueOrDefault<string>("accessRequest");
            var mergedRequest = $@"{accessRequest}{trackRequest}";
            return mergedRequest;
        }</set-body>
        <set-header  name="Content-Type"  exists-action="override">
            <value>application/xml</value>
        </set-header>
    </inbound>
    

    I am able get the expected output.

    enter image description here enter image description here enter image description here