'Condition to check context.Request.Body is JArray or JObject in azure api management policy

I am using Azure API Management policy expression to send the Supplier value into each post, put and delete request to backend API. I wrote a code which was working fine when the request type of JObject. but I have some case where the request can be type of JArray, in that case it throw 500 error. The below snippet is working fine for JObject.

    <set-variable name="Supplier" value="DummySupplier" />
    <choose>
        <when condition="@(new [] {"post", "put", "delete"}.Contains(context.Request.Method, StringComparer.OrdinalIgnoreCase))">
            <set-body>@{ 
                         JObject body = context.Request.Body.As<JObject>(); 
                         body.Add(new JProperty("Supplier", ((string)context.Variables["Supplier"])));
                         return body.ToString(); 
                      }
            </set-body>
        </when>
    </choose>

I need a condition where I can check the request body type and parse accordingly. Otherwise in case of if request body is IEnumerable/JArray type, then above code gives me error.

Getting below error when I have an IEnumerable in request body

The message body is not a valid JSON. Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.

at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.AsJObject(Stream stream, Encoding encoding, JsonSerializerSettings settings)
at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.As[T](Boolean preserveContent)

Could you please help me out with this?



Solution 1:[1]

Not the cleanest solution, but works considering your requirement here. Note that I am now parsing as JToken below which is the base of both JObject and JArray. Then doing things after checking the type.

<set-variable name="Supplier" value="DummySupplier" />
    <choose>
        <when condition="@(new [] {"post", "put", "delete"}.Contains(context.Request.Method, StringComparer.OrdinalIgnoreCase))">
            <set-body>@{ 
                         JToken body = context.Request.Body.As<JToken>();
                         if (body.Type == JTokenType.Array)
                         {
                             JObject newBody = new JObject();
                             newBody["OriginalArray"] = body;
                             newBody["Supplier"] = (string)context.Variables["Supplier"];                             
                             return newBody.ToString();
                         }

                         if (body.Type == JTokenType.Object)
                         {
                             body["Supplier"] = (string)context.Variables["Supplier"];
                             return body.ToString();
                         }
                         
                         return context.Request.Body.ToString();
                       }
            </set-body>
        </when>
    </choose>

Solution 2:[2]

If I use below , I get below error. Error in element 'set-body' on line 30, column 15: Usage of member 'ToString' of type 'System.Object' is not supported within expressions

My outbound policy look like this.

 <outbound>
    <base />
    <return-response>
        <set-status code="200" reason="Success" />
        <set-header name="Accept-Encoding" exists-action="override">
            <value>deflate</value>
        </set-header>
        <set-header name="WWW-Authenticate" exists-action="override">
            <value>PatientID Received="PatientKey0001"</value>
        </set-header>
         <set-body>@{ 
                     JToken body = context.Request.Body.As<JToken>();
                     if (body.Type == JTokenType.Array)
                     {
                         
                     }

                     if (body.Type == JTokenType.Object)
                     {
                        
                     }
                     
                     return context.Request.Body.ToString();
                   }
        </set-body>
    </return-response>
</outbound>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Nasir Khan