REST defines a style of architecture-focused resources. These resources are accessed using URIs and HTTP verbs (GET, POST, PUT and DELETE) rather than based on the SOAPAction as SOAP HTTP.
Some of the benefits of REST are:
-
Lightweight. Excluding extra xml as SOAP packets.
-
The result returned by REST is easily understandable. Is Human Readable.
-
No need toolkits for use.
-
Simple. Obviously has less functionality than a service based on soap/WS- *, but in many cases should be sufficient with this functionality.
If we were to invoke a RESTFUL web service that returned us a customer identifier (25) . The URI to invoke this resource would be as follows:
http://demo/ventas.svc/cliente/25
However in the case of a SOAP Web service through the URI we could only identify the endpoint of the service:
http://demo/ventas.svc
At most the operation to invoke:
http://demo.ventas.asmx?op=ObtenerClientes
Once you "know" that is REST, we will implement a RESTful service based on WCF.
Service Creation
- First of all we must create a new service, for this we will build on the default template for VS 2008. Call RESTService project.

2. Rename the file IService1 by ICalc and modifies the contents of it with the following code:
using System;using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
namespace RESTService{
[ServiceContract]
public interface ICalculadora
{
[OperationContract]
[WebGet(
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate="/Sumar/{op1}/{op2}")]
string Sumar(string op1,string op2);
}
}
The only difference between a WCF Service is that we have added the attribute WebGet to the method Sum. This attribute indicates that the operation is a recovery one and can be called via the web programming model. Furthermore, we indicate that the URI to access to the resource is:
http://servidor/RESTService.Calculadora.svc/Sum/25/50.
Note: You will see that the parameters in this case should be numeric but are string. This is because it is required by UriTemplate.
In the case that the operation is not a recovery operation , we must use the [WebInvoke] attribute.
Sample:
1: [OperationContract]
2: [WebInvoke(Method="DELETE",UriTemplate="/Product/{idProduct}")]
3: public void DeleteProduct(string idProduct)
4: {
5: // Delete the product
6: }
3. Rename the file Service1.cs by Calc.cs and modifies the contents of it with the following code:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Runtime.Serialization;
5: using System.ServiceModel;
6: using System.Text;
7: namespace RESTService
8: {
9: public class Calc : ICalc
10: {
11: public string Sum(string op1, string op2)
12: {
13: int operator1=0;
14: int operator2=0;
15: string sResult = "";
16: if ((int.TryParse(op1, out operator1)) && (int.TryParse(op2, out operator2)))
17: {
18: sResult = string.Format("The result is: {0}", operator1 + operator2);
19: }
20: return sResult;
21: }
22: }
23: }
As you can see, this code implements a method which has two parameters and returns the sum as a result . There's no difference between a "traditional" Service and RESTful.
4. Verify that int the app.config file are reflected all the changes we have made names for code files.
5. Locate the endpoint definition and change wsHttpbinding by webHttpbinding. At the end you should have something like the following.
1: <endpoint address="" binding="webHttpBinding"
2: contract="RESTService.ICalc"
3: behaviorConfiguration="WebBehavior">
6. Add the following xml node inside <behaviors>:
1: <endpointBehaviors>
2: <behavior name="WebBehavior">
3: <webHtpp/>
4: </behavior>
5: </endpointBehaviors>
The binding webHttpbinding indicates that this service should be exposed via HTTP requests exposing Plain old XML (POX) instead of SOAP-based messages. This binding is used in conjunction with behavior WebHttp to enable web programming model for WCF service.
With this we have already created a RESTful service.
Consuming Service
RESTful services can be invoked in two ways:
1. Invoking the service directly through the object WebChannelFactory.
2. Adding a reference to the service and minimally changing the proxy.
I prefer the last one, because everything is much cleaner and we invoke all the services in the same way regardless of how they are exposed.
Method 1: WebChannelFactory
1. Create a console program used to test the RESTful service.
2. Add a reference to System.ServiceModel.Web namespace .
3. Adds a copy of the ICalculadora.cs to this project.
4. Add the following code to consume the service:
1: WebChannelFactory<ICalc> factory = new WebChannelFactory<ICalc>(new Uri("Service_URI"));
2: ICalc proxy = factory.CreateChannel();
3: string response = proxy.Sum("25","70");
4: ((IDisposable)proxy).Dispose();
Remeber you need change “Service_URI” by the Service URL.
This invoking method does not need a services reference, it is only necessary to gain access to the Service interface.
Method 2 (Add Services Reference)
1. Create a console program used to test the RESTful service.
2. Add a reference to System.ServiceModel.Web namespace .
3. Add a reference to the RESTful service that you want to invoke.
4. Open the file containing the proxy code (Reference.cs) to invoke the service. Locate the Sum method and add the following attribute above:
1: [WebGet(
2: BodyStyle = WebMessageBodyStyle.Bare,
3: ResponseFormat = WebMessageFormat.Xml,
4: UriTemplate = "/Sum/{op1}/{op2}")]
With this attribute the proxy knows how to invoke the service.
5. Open the app.config file and locate the node called <client> and add the service endpoint definition to consume:
1: <endpoint address="service_address" behaviorConfiguration="test"
2: binding="webHttpBinding" contract="ServiceReference1.ICalc"
3: name="WebHttpBinding1"/>
6. Below </client> add the next xml:
1: <behaviors>
2: <endpointBehaviors>
3: <behavior name="test">
4: <webHttp/>
5: </behavior>
6: </endpointBehaviors>
7: </behaviors>
Having made these changes we can invoke the service:
1: CalcClient calc = new ConsoleApplication2.ServiceReference1.CalcClient("WebHttpBinding1");
2: string response = calc.Sum("25","70");
Finally, we will use fiddler to see the calls exchange between the client and HTTP service.
In the case of the REST service call we will get the following trace:
1: GET /RESTService.Calculadora.svc/Sumar/25/70 HTTP/1.1
2: Content-Type: application/xml; charset=utf-8
3: VsDebuggerCausalityData: uIDPo8iVuDxtWzVIoOWhMWz8d6cAAAAAQQ14Z3Np/kGe9oMjdzTKnIAB0WdKCntFi092ERAO19oACQAA
4: Host: xxxxxx
5: Connection: Keep-Alive
In the case of the SOAP service call we will get the following trace:
1: POST /WcfServiceLibrary1.Service1.svc HTTP/1.1
2: Content-Type: text/xml; charset=utf-8
3: VsDebuggerCausalityData: uIDPo9JShnIh9h9LnpM3i3SLcV8AAAAADD0BBgGqLkCAeQs6rXWB4Cv3lHKbfRpOq02eDFtYkC4ACQAA
4: SOAPAction: "http://tempuri.org/IService1/GetData"
5: Host: xxxxxxxx
6: Content-Length: 158
7: Expect: 100-continue
8: Connection: Keep-Alive
9:
10: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
11: <s:Body>
12: <GetData xmlns="http://tempuri.org/">
13: <value>25</value>
14: </GetData>
15: </s:Body>
16: </s:Envelope>
If we compare with another one trace, we will test that in the "REST" Service is the GET operation which defines the method to invoke and the parameters , there is no SOAPAction, while in the "SOAP" Service we need the SOAPAction attribute to define the method to invoke and a envelope where we define the parameters passed to this method.
The service "REST" response is the following:
1: HTTP/1.1 200 OK
2: Content-Type: application/xml; charset=utf-8
3: Server: Microsoft-IIS/7.0
4: X-Powered-By: ASP.NET
5: Date: Mon, 27 Apr 2009 14:33:52 GMT
6: Content-Length: 92
7:
8: <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">The result is: 95</string>
The service "SOAP" response is the following:
1: HTTP/1.1 200 OK
2: Content-Type: text/xml; charset=utf-8
3: Server: Microsoft-IIS/7.0
4: X-Powered-By: ASP.NET
5: Date: Mon, 27 Apr 2009 14:28:00 GMT Content-Length: 203
6:
7:
8:
9: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
10: <s:Body>
11: <GetDataResponse xmlns="http://tempuri.org/">
12: <GetDataResult>You entered: 25</GetDataResult>
13: </GetDataResponse>
14: </s:Body>
15: </s:Envelope>
As we can see in the trace, the "REST" response is much simpler and smaller than the "SOAP" response.
In the next link RESTService.zip you have available the example files. It is a very simple example but it explains the basis for building a REST service.
Finally it is only to say that Microsoft has released a Starter Kit on CodePlex (Preview 2) that provides classes and templates for the creation of RESTful services.
In another post we will see how to create and consume a service using this starter kit.
Regards.
Posted
May 29 2009, 02:25 AM
by
Roberto