Wednesday, April 25, 2012

WCF JSON & SOAP Servce

Exposing services to mobile devices has some challenges, first JSON is efficient reason why iOS and Android make it them standard but SOAP is "the standard" and have a well defined contract. So we do not have to choose... we can have both using WCF.

Ill try to keep this simple, what we need to do is publish one WCF with two endpoints, one for JSON and one for SOAP, so this the solution:

1) Create a Web Project of type WCF Service, lets call it TestWCF

2) Alter web.config
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="false"></compilation>
    <authentication mode="Windows" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonbehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="servicebehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="servicebehavior" name="TestWCF.Service1">
        <endpoint address="soap" binding="basicHttpBinding" name="SOAPEndPoint"
          contract="TestWCF.IService1" />
        <endpoint address="json" behaviorConfiguration="jsonbehavior"
          binding="webHttpBinding" name="JSONEndPoint" contract="TestWCF.IService1JSON" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
</configuration>


3) Define a method to be exposed as SOAP at the IService1.cs contract.
namespace TestWCF
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        List<string> SomeServiceExposed(string anArgument, string otherArgument);
    }
}

4) Create a new contract interface for JSON as IService1JSON.cs
namespace TestWCF
{
    [ServiceContract]
    public interface IService1JSON
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "/SomeServiceExposed", BodyStyle = WebMessageBodyStyle.Wrapped, Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        List<string> SomeServiceExposedJSON(string anArgument, string otherArgument);
    }
}


5) Implement the service at the Service1.svc.sc
namespace TestWCF
{
    public class Service1 : IService1, IService1JSON
    {
        public List<string> SomeServiceExposed(string anArgument, string otherArgument)
        {
            List<string> list = new List<string>();
            list.Add(anArgument);
            list.Add(otherArgument);
            return list;
        }       
       
        public 
List<string> SomeServiceExposedJSON(string anArgument, string otherArgument)
        {
            return this.SomeServiceExposed(anArgument, otherArgument);
        }
    }
}

6) Finally test it, testing the SOAP is straightforward, testing the JSON is like this:
    class Program
    {
        static void Main(string[] args)
        {
            WebClient jsonClient = new WebClient();
            jsonClient.Headers["Content-type"] = "application/json";
            byte[] request = System.Text.Encoding.ASCII.GetBytes(
                "{\"anArgument\":\"Hello\",\"otherArgument\":\"World\"}");
            byte[] response = jsonClient.UploadData(
                "http://localhost:<port>/Service1.svc/json/SomeServiceExposed", "POST", request);
            Console.WriteLine(System.Text.Encoding.ASCII.GetString(response));
        }
    }

No comments: