Api Management: Convert XML to JSON using policies, without any modification of the Api!

Last October I posted a brief introduction to Api Management, one of the new services of the Microsoft Azure platform. Its first goal is to centralize the use of our Apis by others, but the fact is that it allows more: set quotas, rewrite URLs, modify the content response, conversion between formats, and so on. Many of these extra powers are achieved through what is known as policies. In this post I will show you how easy it is to transform the result of Api, which only returns XML, to JSON.

The Api

First, create a service with Windows Communication Foundation, which looks like this:

using System.ServiceModel;
using System.ServiceModel.Web;
using WcfService.Model;
namespace WcfService
{
    [ServiceContract(Namespace = "")]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        Profile GetData(int id, string name, string address);
    }
}

This demo only exposes a method called GetData, which receives all the necessary values to construct and return a Profile object, as shown in its implementation:

using WcfService.Model;
namespace WcfService
{
    public class Service : IService
    {
        public Profile GetData(int id, string name, string address)
        {
            return new Profile { Id = id, Name = name, Address = address };
        }
    }
}

Regarding WCF service configuration, create a binding type webHttpBinding, expose it using a webHttp behaviour and leave the rest of the default settings.

  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webBinding"></binding>
      </webHttpBinding>
    </bindings>
    <services>
      <service name="WcfService.Service" behaviorConfiguration="MyBehavior">
        <endpoint address="xml"
                  binding="webHttpBinding"
                  bindingConfiguration="webBinding"
                  behaviorConfiguration="xmlBehavior"
                  contract="WcfService.IService"/>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="xmlBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="MyBehavior">
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>

Before adding the service to Api Management, we can check the results generated using Fiddler:

Fiddler testing WCF service
Using Fiddler in order to check the XML result

Policies

Remember to add the Api service and associate it with a product, as explained in the introductory post.

In the Policies section, choose the GetData method through the combos and select the ADD POLICY option in the lower box.

Policies combo and add policy
Choose the method through combos and select the ADD POLICY option in the lower box

From this point the policy setting box will be activated, showing the following information:

<!--
    IMPORTANT:
        - Policy statements MUST be enclosed within either <inbound> or <outbound> elements.
        - <base /> elements represent policy-in-effect inherited from the outer scopes.
        - <inbound> element contains policies to be applied in the inbound direction (from caller to web service).
        - <outbound> element contains policies to be applied in the outbound direction (from web service to caller).
        - Policies are applied in the order they appear.
    To ADD a policy, position cursor in the policy document to specify the insertion point and click on the associated button for a desired policy statement button.
    To REMOVE a policy, delete the corresponding policy statement from the policy document.
    To RE-ORDER a policy, select the corresponding policy statement and cut-and-paste it into a new location within the policy document.
-->
<policies>
    <inbound>
        <base />
    </inbound>
    <outbound>

The setup is simple: the base tag is used to inherit all the policies that are defined at higher levels. Inbound policy is used to specify input policies and outbound for output policies. In order to convert XML to JSON you should use an outbound policy. To create it position the cursor in the outbound section and click on Convert XML to JSON link.

Policy Outbound  Convert XML to JSON
Position the cursor in the outbound section and click on Convert XML to JSON link.

This is the line we got with that action:

<xml-to-json kind="javascript-friendly | direct" apply="always | content-type-xml" consider-accept-header="true | false"/>

There is a section in the documentation of Api Management, called Azure Management API Reference Policy, where we can see all the values and policies that are currently supported. On this example, we know what values can be configured here. This is the configuration I’ve chosen:

<xml-to-json kind="javascript-friendly" apply="content-type-xml" consider-accept-header="true"/>

Developer portal

The easiest way to check the policy is working properly is using the Developer Portal, which is accessible from the top menu of the management portal. Once there, choose the service from the APIS section and open the console. If you introduce three random values for the parameters and click on HTTP GET button it should display the result in XML format.

Api Response content without headers
XML result

To get the JSON conversion, just add accept: application/json in the request headers box:

Api get profile accept json example
Request with Accept: application/json header

If you check the result, this time will have been converted to JSON:

Api response content with header
JSON result using Accept: application/json header

Cheers!