Client configuration to consume WCF JSON web service

I have configured the web service to use Json as described on this blog: http://www.west-wind.com/weblog/posts/164419.aspx and various other blogs, but I couldn't create a client to consume this service. I tried various things, but invariably I got meaningless exceptions. What is the correct way to implement the (WCF I should add) client?


Solution 1:

There seems to be a shortage of examples about how to write a WCF client for a JSON REST service. Everybody seems to use WCF for implementing the service but hardly ever for writing a client. So here's a rather complete example of the service (implementing a GET and a POST request) and the client.

Service

Service interface

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "/getcar/{id}")]
    Car GetCar(string id);

    [OperationContract]
    [WebInvoke(RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "/updatecar/{id}")]
    Car UpdateCar(string id, Car car);
}

Service data structures

[DataContract]
public class Car
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string Make { get; set; }
}

Service implementation

public class Service1 : IService1
{
    public Car GetCar(string id)
    {
        return new Car { ID = int.Parse(id), Make = "Porsche" };
    }

    public Car UpdateCar(string f, Car car)
    {
        return car;
    }
}

Service markup

<%@ ServiceHost Language="C#" Service="JSONService.Service1"
    CodeBehind="Service1.svc.cs"
    Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>   
</configuration>

Client

And now the client. It reuses the interface IService1 and the class Car. In addition, the following code and configuration is required.

App.config

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webby">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address="http://localhost:57211/Service1.svc" name="Service1" binding="webHttpBinding" contract="JSONService.IService1" behaviorConfiguration="webby"/>
    </client>
  </system.serviceModel>
</configuration>

Program.cs

public class Service1Client : ClientBase<IService1>, IService1
{
    public Car GetCar(string id)
    {
        return base.Channel.GetCar(id);
    }


    public Car UpdateCar(string id, Car car)
    {
        return base.Channel.UpdateCar(id, car);
    }
}


class Program
{
    static void Main(string[] args)
    {
        Service1Client client = new Service1Client();
        Car car = client.GetCar("1");
        car.Make = "Ferrari";
        car = client.UpdateCar("1", car);
    }
}

Have fun.