Consuming REST Services with WCF-Clients

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

This post describes how to consume the REST Service with WCF-based client. In general there are two ways to do this:

1. You send the HTTP request and serialize the data
2. You let the WCF to do this for you.

Actually, you might be interested to do this by using of variant 2. However I will show the first the variant 1 to get more ffeling what happens behind the scene.

In this example I have used the service with following contract:

[ServiceContract()]
public interface IJsonGpsService
{
  [OperationContract]
  [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
         ResponseFormat = WebMessageFormat.Json)]

   Airport[] GetCoordinates();
}

The service IJsonGpsService retrieves the GPS coordinates of all airports in the array of Airport. If the service is setup for JSON serialization as shown in the interface above you can test it by simply entering of the URL in the browser's address window:

http://localhost:81/GetJsonCoordinates.svc/getcoordinates

After sending of request the browser (in my case IE) will popup following dialog:

image
This means that the browser cannot deserialize the JSON data. Anyhow, you can save the response in the file and open it. In this case the response in the file would look like:
 

{"d":[{"__type":"Airport:#Microsoft.ServiceModel.Samples.BasicSyndication","Contacts":[{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"damir","LastName":"dobric"},{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-87.652778,"Longitude":34.691111,"Name":"5AL5"},{"__type":"Airport:#Microsoft.ServiceModel.Samples.BasicSyndication","Contacts":[{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"damir","LastName":"dobric"},{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-
..
{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-161.837997,"Longitude":60.779778,"Name":"PABE"}]}

It is obvious that the browser cannot understand this response. To make the response more understandable for browser the contract could to be slightly changed  to enforce XML serialization (in a case of WCF this means DataContractSerializer by default):

[ServiceContract()]
public interface IJsonGpsService
{
  [OperationContract]
  [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
         ResponseFormat = WebMessageFormat.Xml)]

   Airport[] GetCoordinates();
}

Rebuild the service and enter again the same URL in the browser. This is now the XML-based snapshot of the response:

image

 

Consuming with serialization

To consume this service by using of the first variant you are responsible to send the request and to serialize the data. Assuming that the WCF service is build by using of WCF-technology, it is likely that the data on the wire are serialized by using of DataContractSerializer. Another alternative would be using of XmlSerializer. Here is the full example which shows how to do this:

WebRequest request = WebRequest.Create(
“http://localhost:81/GetJsonCoordinates.svc/getcoordinates");

WebResponse ws = request.GetResponse();
DataContractSerializer ser =
new DataContractSerializer(typeof(Airport[]));

//
// here is another alternative.
//XmlSerializer ser = new XmlSerializer(typeof(Airport[]));
Airport[] airports = (Airport[])ser.ReadObject(ws.GetResponseStream());

 

Consuming with real WCF client

In the real world you will and should not do it this way. You would probable open VS and add service reference. Unfortunately this will not help you mach. The bindings created on the client side will be invalid and two endpoint will be created. It will not work.
To make it working do folowing:

1. Add service reference by using the URI http://localhost:81/GetJsonCoordinates.svc. (assuming that MEX binding is enabled).
2. Remove one of two created bindings in the client's configuration file (under the section <client>).
3. Add the endpoint behavior ("AjaxBehavior") with the webHtt element (enableWebScript is required for AJAX).
4. Add the webHttpConfiguration element (if some none-default settings are used - in this example basic-clear text. Do not use this in productive environment!)

5. Add the address element in the endpoint with the URI of the service. (VS does not add this by adding of reference)
6. Finally change the interface which has been automatically created by WS during add service reference operation, as shown below:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IJsonGpsService")]
public interface IJsonGpsService
{   
  
[System.ServiceModel.OperationContractAttribute 
   (Action=http://tempuri.org/IJsonGpsService/GetCoordinates,
    ReplyAction=http://tempuri.org/IJsonGpsService/GetCoordinatesResponse)
   [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
    ResponseFormat = WebMessageFormat.Xml)]TestClient.ServiceReference1.Airport[]
    GetCoordinates();
}

In the interface above I have added the WebGet attribute. VS didn't create this automatically.

Here is the full configuration which corresponds to changes described in steps 1-5 above:


image

Following code snippet shows the consumer's code which consumes the REST-service by using of WCF. Before this code can run you have to perform changes described in the step 6 above.

JsonGpsServiceClient json = new JsonGpsServiceClient();

json.ClientCredentials.UserName.UserName = "..";
json.ClientCredentials.UserName.Password = "..";


airports = json.GetCoordinates();

 

Lst but not least: Please note that the message format defined in the interface at both sides has to be the some. If it is not the same (for example Service JSON and Client XML) no exception will be thrown, but the data in the response will be empty as shown in the next picture:
image


Posted Dec 25 2008, 06:58 PM by Damir Dobric

Comments

jefflouella.com wrote re: Consuming REST Services with WCF-Clients
on 03-09-2009 14:31

Gute Arbeit hier! Gute Inhalte.

developers.de is a .Net Community Blog powered by daenet GmbH.